From d4071f46641223f7c683ce3eba6cc233ca36e152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Thu, 25 Apr 2024 17:01:34 +0000 Subject: [PATCH 01/39] Add custom proposal implementation Lacks setting of custom proposal configuration during deployment --- src/proposals.cairo | 72 +++++++++++++++++++++++++++++++++++++++------ src/types.cairo | 14 ++++++--- src/upgrades.cairo | 41 +++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 14 deletions(-) diff --git a/src/proposals.cairo b/src/proposals.cairo index a0a41e8f..a16e429c 100644 --- a/src/proposals.cairo +++ b/src/proposals.cairo @@ -16,6 +16,9 @@ trait IProposals<TContractState> { fn get_user_voted( self: @TContractState, user_address: ContractAddress, prop_id: felt252 ) -> VoteStatus; + fn submit_custom_proposal( + ref self: TContractState, custom_proposal_type: u32, calldata: Span<felt252> + ) -> u32; } #[starknet::component] @@ -34,11 +37,13 @@ mod proposals { use hash::LegacyHash; use starknet::contract_address::ContractAddressZeroable; + use starknet::class_hash::ClassHashZeroable; use starknet::get_block_info; use starknet::get_block_timestamp; use starknet::get_caller_address; use starknet::BlockInfo; use starknet::ContractAddress; + use starknet::ClassHash; use starknet::contract_address_const; use starknet::event::EventEmitter; use starknet::get_contract_address; @@ -51,6 +56,7 @@ mod proposals { use governance::types::ContractType; use governance::types::PropDetails; use governance::types::VoteStatus; + use governance::types::CustomProposalConfig; use governance::traits::IERC20Dispatcher; use governance::traits::IERC20DispatcherTrait; use governance::traits::get_governance_token_address_self; @@ -67,6 +73,10 @@ mod proposals { proposal_applied: LegacyMap::<felt252, felt252>, // should be Bool after migration delegate_hash: LegacyMap::<ContractAddress, felt252>, total_delegated_to: LegacyMap::<ContractAddress, u128>, + custom_proposal_type: LegacyMap::<u32, CustomProposalConfig>, // custom proposal type + custom_proposal_payload: LegacyMap::< + (u32, u32), felt252 + > // mapping from prop_id and index to calldata } #[derive(starknet::Event, Drop)] @@ -221,6 +231,17 @@ mod proposals { .update_calldata(to_addr, new_amount, calldata_span, new_list, index + 1_usize); } } + + fn assert_eligible_to_propose(self: @ComponentState<TContractState>) { + let user_address = get_caller_address(); + let govtoken_addr = get_governance_token_address_self(); + let caller_balance: u128 = IERC20Dispatcher { contract_address: govtoken_addr } + .balanceOf(user_address) + .low; + let total_supply = IERC20Dispatcher { contract_address: govtoken_addr }.totalSupply(); + let res: u256 = (caller_balance * constants::NEW_PROPOSAL_QUORUM).into(); + assert(total_supply < res, 'not enough tokens to submit'); + } } #[embeddable_as(ProposalsImpl)] @@ -275,15 +296,7 @@ mod proposals { ref self: ComponentState<TContractState>, payload: felt252, to_upgrade: ContractType ) -> felt252 { assert_correct_contract_type(to_upgrade); - let govtoken_addr = get_governance_token_address_self(); - let caller = get_caller_address(); - let caller_balance: u128 = IERC20Dispatcher { contract_address: govtoken_addr } - .balanceOf(caller) - .low; - let total_supply = IERC20Dispatcher { contract_address: govtoken_addr }.totalSupply(); - let res: u256 = (caller_balance * constants::NEW_PROPOSAL_QUORUM) - .into(); // TODO use such multiplication that u128 * u128 = u256 - assert(total_supply < res, 'not enough tokens to submit'); + self.assert_eligible_to_propose(); let prop_id = self.get_free_prop_id_timestamp(); let prop_details = PropDetails { payload: payload, to_upgrade: to_upgrade.into() }; @@ -297,6 +310,47 @@ mod proposals { prop_id } + fn submit_custom_proposal( + ref self: ComponentState<TContractState>, + custom_proposal_type: u32, + mut calldata: Span<felt252> + ) -> u32 { + let config: CustomProposalConfig = self.custom_proposal_type.read(custom_proposal_type); + assert( + config.target.is_non_zero(), 'custom prop classhash 0' + ); // wrong custom proposal type? + assert( + config.selector.is_non_zero(), 'custom prop selector 0' + ); // wrong custom proposal type? + self.assert_eligible_to_propose(); + + let prop_id_felt = self.get_free_prop_id_timestamp(); + let prop_id: u32 = prop_id_felt.try_into().unwrap(); + let payload = custom_proposal_type.into(); + let prop_details = PropDetails { + payload, to_upgrade: 5 + }; // to_upgrade = 5 – custom proposal type. + self.proposal_details.write(prop_id_felt, prop_details); + + let current_timestamp: u64 = get_block_timestamp(); + let end_timestamp: u64 = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + self.proposal_vote_end_timestamp.write(prop_id_felt, end_timestamp); + self.emit(Proposed { prop_id: prop_id_felt, payload, to_upgrade: 5 }); + + self.custom_proposal_payload.write((prop_id, 0), calldata.len().into()); + let mut i: u32 = 1; + loop { + match calldata.pop_front() { + Option::Some(argument) => { + self.custom_proposal_payload.write((prop_id, i), *argument); + i += 1; + }, + Option::None(()) => { break (); } + } + }; + prop_id + } + // fn delegate_vote( // ref self: ComponentState<TContractState>, diff --git a/src/types.cairo b/src/types.cairo index b2984def..df232ee6 100644 --- a/src/types.cairo +++ b/src/types.cairo @@ -1,6 +1,5 @@ use starknet::SyscallResult; -use starknet::syscalls::storage_read_syscall; -use starknet::syscalls::storage_write_syscall; +use starknet::syscalls::{storage_read_syscall, storage_write_syscall, ClassHash}; use starknet::storage_address_from_base_and_offset; use core::serde::Serde; @@ -16,8 +15,15 @@ struct VoteCounts { } type BlockNumber = felt252; -type VoteStatus = felt252; // 0 = not voted, 1 = yay, -1 = nay +type VoteStatus = felt252; // 0 = not voted, 1 = yay, 2 = nay type ContractType = - u64; // for Carmine 0 = amm, 1 = governance, 2 = CARM token, 3 = merkle tree root, 4 = no-op/signal vote + u64; // for Carmine 0 = amm, 1 = governance, 2 = CARM token, 3 = merkle tree root, 4 = no-op/signal vote, 5 = custom proposal type OptionSide = felt252; type OptionType = felt252; + +#[derive(Copy, Drop, Serde, starknet::Store)] +struct CustomProposalConfig { + target: felt252, //class hash if library call, contract address if regular call + selector: felt252, + library_call: bool +} diff --git a/src/upgrades.cairo b/src/upgrades.cairo index b7ec6f1e..e05982f9 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -5,6 +5,8 @@ trait IUpgrades<TContractState> { #[starknet::component] mod upgrades { + use core::result::ResultTrait; + use core::array::ArrayTrait; use traits::TryInto; use option::OptionTrait; use traits::Into; @@ -16,7 +18,7 @@ mod upgrades { use starknet::ContractAddress; use starknet::class_hash; - use governance::types::PropDetails; + use governance::types::{CustomProposalConfig, PropDetails}; use governance::contract::Governance; use governance::contract::Governance::ContractState; @@ -92,6 +94,43 @@ mod upgrades { } else if (contract_type == 3) { let mut airdrop_comp = get_dep_component_mut!(ref self, Airdrop); airdrop_comp.merkle_root.write(impl_hash); + } else if (contract_type == 5) { + // custom proposal + let custom_proposal_type: u32 = impl_hash + .try_into() + .expect('custom prop type fit in u32'); + let config: CustomProposalConfig = proposals_comp + .custom_proposal_type + .read(custom_proposal_type); + + let prop_id_: u32 = prop_id.try_into().unwrap(); + let mut calldata_len = proposals_comp + .custom_proposal_payload + .read((prop_id_, 0)); + let mut calldata: Array<felt252> = ArrayTrait::new(); + let mut i: u32 = 1; + while (calldata_len != 0) { + calldata + .append(proposals_comp.custom_proposal_payload.read((prop_id_, i))); + i += 1; + calldata_len -= 1; + }; + + if (config.library_call) { + let res = syscalls::library_call_syscall( + config.target.try_into().expect('unable to convert>classhash'), + config.selector, + calldata.span() + ); + res.expect('libcall failed'); + } else { + let res = syscalls::call_contract_syscall( + config.target.try_into().expect('unable to convert>addr'), + config.selector, + calldata.span() + ); + res.expect('contract call failed'); + } } else { assert( contract_type == 4, 'invalid contract_type' From 25ec5d5394ddfe2f7a1c9be58e62446802147ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Fri, 26 Apr 2024 14:31:11 +0000 Subject: [PATCH 02/39] Add arbitrary proposal --- src/proposals.cairo | 2 +- src/upgrades.cairo | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/proposals.cairo b/src/proposals.cairo index a16e429c..5ada97f9 100644 --- a/src/proposals.cairo +++ b/src/proposals.cairo @@ -101,7 +101,7 @@ mod proposals { } fn assert_correct_contract_type(contract_type: ContractType) { - assert(contract_type <= 4, 'invalid contract type') + assert(contract_type <= 6, 'invalid contract type') } fn hashing( diff --git a/src/upgrades.cairo b/src/upgrades.cairo index e05982f9..ba141ef1 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -10,6 +10,7 @@ mod upgrades { use traits::TryInto; use option::OptionTrait; use traits::Into; + use core::SpanTrait; use starknet::SyscallResultTrait; use starknet::SyscallResult; @@ -131,6 +132,14 @@ mod upgrades { ); res.expect('contract call failed'); } + } else if (contract_type == 6) { + // arbitrary proposal + let res = syscalls::library_call_syscall( + impl_hash.try_into().expect('unable to convert>classhash'), + selector!("execute_arbitrary_proposal"), + ArrayTrait::new().span() + ); + res.expect('libcall failed'); } else { assert( contract_type == 4, 'invalid contract_type' From 676a2e26e82c855ba443558c8b098b6828c6249b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Fri, 26 Apr 2024 14:45:24 +0000 Subject: [PATCH 03/39] Polish apply_passed_proposal --- src/upgrades.cairo | 113 ++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/src/upgrades.cairo b/src/upgrades.cairo index ba141ef1..edc82a8e 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -77,76 +77,75 @@ mod upgrades { let impl_hash = prop_details.payload; // Apply the upgrade - // TODO use full match/switch when supported match contract_type { 0 => { let amm_addr: ContractAddress = get_amm_address_self(); IAMMDispatcher { contract_address: amm_addr } .upgrade(impl_hash.try_into().unwrap()); }, - _ => { - if (contract_type == 1) { - let impl_hash_classhash: ClassHash = impl_hash.try_into().unwrap(); - syscalls::replace_class_syscall(impl_hash_classhash); - } else if (contract_type == 2) { - let govtoken_addr = get_governance_token_address_self(); - IGovernanceTokenDispatcher { contract_address: govtoken_addr } - .upgrade(impl_hash); - } else if (contract_type == 3) { - let mut airdrop_comp = get_dep_component_mut!(ref self, Airdrop); - airdrop_comp.merkle_root.write(impl_hash); - } else if (contract_type == 5) { - // custom proposal - let custom_proposal_type: u32 = impl_hash - .try_into() - .expect('custom prop type fit in u32'); - let config: CustomProposalConfig = proposals_comp - .custom_proposal_type - .read(custom_proposal_type); + 1 => { + let impl_hash_classhash: ClassHash = impl_hash.try_into().unwrap(); + let res = syscalls::replace_class_syscall(impl_hash_classhash); + res.expect('upgrade failed'); + }, + 2 => { + let govtoken_addr = get_governance_token_address_self(); + IGovernanceTokenDispatcher { contract_address: govtoken_addr } + .upgrade(impl_hash); + }, + 3 => { + let mut airdrop_comp = get_dep_component_mut!(ref self, Airdrop); + airdrop_comp.merkle_root.write(impl_hash); + }, + 4 => (), + 5 => { + // custom proposal + let custom_proposal_type: u32 = impl_hash + .try_into() + .expect('custom prop type fit in u32'); + let config: CustomProposalConfig = proposals_comp + .custom_proposal_type + .read(custom_proposal_type); - let prop_id_: u32 = prop_id.try_into().unwrap(); - let mut calldata_len = proposals_comp - .custom_proposal_payload - .read((prop_id_, 0)); - let mut calldata: Array<felt252> = ArrayTrait::new(); - let mut i: u32 = 1; - while (calldata_len != 0) { - calldata - .append(proposals_comp.custom_proposal_payload.read((prop_id_, i))); - i += 1; - calldata_len -= 1; - }; + let prop_id_: u32 = prop_id.try_into().unwrap(); + let mut calldata_len = proposals_comp + .custom_proposal_payload + .read((prop_id_, 0)); + let mut calldata: Array<felt252> = ArrayTrait::new(); + let mut i: u32 = 1; + while (calldata_len != 0) { + calldata.append(proposals_comp.custom_proposal_payload.read((prop_id_, i))); + i += 1; + calldata_len -= 1; + }; - if (config.library_call) { - let res = syscalls::library_call_syscall( - config.target.try_into().expect('unable to convert>classhash'), - config.selector, - calldata.span() - ); - res.expect('libcall failed'); - } else { - let res = syscalls::call_contract_syscall( - config.target.try_into().expect('unable to convert>addr'), - config.selector, - calldata.span() - ); - res.expect('contract call failed'); - } - } else if (contract_type == 6) { - // arbitrary proposal + if (config.library_call) { let res = syscalls::library_call_syscall( - impl_hash.try_into().expect('unable to convert>classhash'), - selector!("execute_arbitrary_proposal"), - ArrayTrait::new().span() + config.target.try_into().expect('unable to convert>classhash'), + config.selector, + calldata.span() ); res.expect('libcall failed'); } else { - assert( - contract_type == 4, 'invalid contract_type' - ); // type 4 is no-op, signal vote + let res = syscalls::call_contract_syscall( + config.target.try_into().expect('unable to convert>addr'), + config.selector, + calldata.span() + ); + res.expect('contract call failed'); } - } - } + }, + 6 => { + // arbitrary proposal + let res = syscalls::library_call_syscall( + impl_hash.try_into().expect('unable to convert>classhash'), + selector!("execute_arbitrary_proposal"), + ArrayTrait::new().span() + ); + res.expect('libcall failed'); + }, + _ => {panic_with_felt252('invalid to_upgrade')} + }; self.proposal_applied.write(prop_id, true); // Mark the proposal as applied self .emit( From d1780365d8a8b42c32c461f4fe829737580a12a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Fri, 26 Apr 2024 14:47:26 +0000 Subject: [PATCH 04/39] Polish scarb fmt --- src/upgrades.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/upgrades.cairo b/src/upgrades.cairo index edc82a8e..b8545bf0 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -144,7 +144,7 @@ mod upgrades { ); res.expect('libcall failed'); }, - _ => {panic_with_felt252('invalid to_upgrade')} + _ => { panic_with_felt252('invalid to_upgrade') } }; self.proposal_applied.write(prop_id, true); // Mark the proposal as applied self From 18508143404590a7f927baea0b501372b85bb881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Tue, 30 Apr 2024 13:13:26 +0000 Subject: [PATCH 05/39] Cherry pick setup.cairo from 1fab54f --- tests/setup.cairo | 175 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 tests/setup.cairo diff --git a/tests/setup.cairo b/tests/setup.cairo new file mode 100644 index 00000000..7d240631 --- /dev/null +++ b/tests/setup.cairo @@ -0,0 +1,175 @@ +use core::traits::Into; +#[starknet::contract] +mod MyToken { + use openzeppelin::token::erc20::ERC20Component; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>; + impl InternalImpl = ERC20Component::InternalImpl<ContractState>; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, fixed_supply: u256, recipient: ContractAddress) { + let name = 'MyToken'; + let symbol = 'MTK'; + + self.erc20.initializer(name, symbol); + self.erc20._mint(recipient, fixed_supply); + } +} + +use array::ArrayTrait; +use core::traits::TryInto; +use debug::PrintTrait; +use starknet::ContractAddress; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use snforge_std::{ + BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget +}; + +use governance::contract::IGovernanceDispatcher; +use governance::contract::IGovernanceDispatcherTrait; +use governance::proposals::IProposalsDispatcher; +use governance::proposals::IProposalsDispatcherTrait; +use governance::upgrades::IUpgradesDispatcher; +use governance::upgrades::IUpgradesDispatcherTrait; +use governance::constants; +use starknet::get_block_timestamp; + + +const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; + +const first_address: ContractAddress = 0x1.try_into().unwrap(); +const second_address: ContractAddress = 0x2.try_into().unwrap(); +const admin_addr: ContractAddress = 0x3.try_into().unwrap(); + +fn deploy_governance() -> IGovernanceDispatcher { + let gov_contract = declare('Governance'); + let address = gov_contract.deploy().expect('unable to deploy governance'); + IGovernanceDispatcher { contract_address: address }; +} + + +fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) { + let mut calldata = ArrayTrait::new(); + calldata.append(GOV_TOKEN_INITIAL_SUPPLY); + calldata.append(recipient.into()); + + let gov_token_contract = declare('MyToken'); + let token_addr = gov_token_contract.deploy_at(@calldata).expect('unable to deploy MyToken'); + let token: IERC20Dispatcher = IERC20Dispatcher { contract_address: token_addr }; + + start_prank(CheatTarget::One(token_addr), admin_addr); + + token.transfer(first_address, 100000); + token.transfer(second_address, 100000); +} + + +fn test_vote_upgrade_root(new_merkle_root: felt252) { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(new_merkle_root, 3); + + start_prank(CheatTarget::One(gov_contract_addr), first_address); + dispatcher.vote(prop_id, 1); + start_prank(CheatTarget::One(gov_contract_addr), second_address); + dispatcher.vote(prop_id, 1); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + dispatcher.vote(prop_id, 1); + + assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); + + let upgrade_dispatcher = IUpgradesDispatcher { contract_address: gov_contract_addr }; + upgrade_dispatcher.apply_passed_proposal(prop_id); + assert(check_if_healthy(gov_contract_addr), 'new gov not healthy'); +} + +fn check_if_healthy(gov_contract_addr: ContractAddress) -> bool { + // TODO + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + dispatcher.get_proposal_status(0); + let prop_details = dispatcher.get_proposal_details(0); + (prop_details.payload + prop_details.to_upgrade) != 0 +} + + +fn test_express_proposal() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + dispatcher.vote(prop_id, 1); + + assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); +} + +#[should_panic] +fn test_proposal_expiry() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + //simulate passage of time + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + start_warp(end_timestamp + 1, current_timestamp); + + let status = dispatcher.get_proposal_status(prop_id); +} + +#[should_panic] +fn test_vote_on_expired_proposal() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + //simulate passage of time + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + start_warp(end_timestamp + 1, current_timestamp); + + start_prank(CheatTarget::One(gov_contract_addr), first_address); + dispatcher.vote(prop_id, 1); +} + From 4a308b9063b1eb40054029230ec80bdd2fd353ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Tue, 30 Apr 2024 13:14:04 +0000 Subject: [PATCH 06/39] Move test setup to src/ --- src/lib.cairo | 3 +++ {tests => src/testing}/setup.cairo | 0 tests/lib.cairo | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) rename {tests => src/testing}/setup.cairo (100%) diff --git a/src/lib.cairo b/src/lib.cairo index 44a80fc1..6b9d0ec4 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -13,3 +13,6 @@ mod treasury; mod types; mod upgrades; mod voting_token; +mod testing { + mod setup; +} diff --git a/tests/setup.cairo b/src/testing/setup.cairo similarity index 100% rename from tests/setup.cairo rename to src/testing/setup.cairo diff --git a/tests/lib.cairo b/tests/lib.cairo index 4499bc14..b79504c6 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -1,3 +1,5 @@ -mod test_treasury; -mod basic; mod add_options; +mod basic; +mod custom_proposals; +mod setup; +mod test_treasury; From 03d1ba537c1030475740e277a5a5188a66b6d13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Tue, 30 Apr 2024 13:29:31 +0000 Subject: [PATCH 07/39] Remove unrelated functions from setup.cairo --- src/testing/setup.cairo | 57 ----------------------------------------- 1 file changed, 57 deletions(-) diff --git a/src/testing/setup.cairo b/src/testing/setup.cairo index 7d240631..f822676b 100644 --- a/src/testing/setup.cairo +++ b/src/testing/setup.cairo @@ -116,60 +116,3 @@ fn check_if_healthy(gov_contract_addr: ContractAddress) -> bool { let prop_details = dispatcher.get_proposal_details(0); (prop_details.payload + prop_details.to_upgrade) != 0 } - - -fn test_express_proposal() { - let gov_contract = deploy_governance(); - let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); - - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - let prop_id = dispatcher.submit_proposal(42, 1); - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - dispatcher.vote(prop_id, 1); - - assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); -} - -#[should_panic] -fn test_proposal_expiry() { - let gov_contract = deploy_governance(); - let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); - - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - let prop_id = dispatcher.submit_proposal(42, 1); - - //simulate passage of time - let current_timestamp = get_block_timestamp(); - let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(end_timestamp + 1, current_timestamp); - - let status = dispatcher.get_proposal_status(prop_id); -} - -#[should_panic] -fn test_vote_on_expired_proposal() { - let gov_contract = deploy_governance(); - let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); - - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - let prop_id = dispatcher.submit_proposal(42, 1); - - //simulate passage of time - let current_timestamp = get_block_timestamp(); - let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(end_timestamp + 1, current_timestamp); - - start_prank(CheatTarget::One(gov_contract_addr), first_address); - dispatcher.vote(prop_id, 1); -} - From 82d79473c519bdff9fb4fb0b4c2af27034e39a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Tue, 30 Apr 2024 13:39:46 +0000 Subject: [PATCH 08/39] Fix setup --- src/testing/setup.cairo | 81 ++++++++++++----------------------------- tests/lib.cairo | 1 - 2 files changed, 24 insertions(+), 58 deletions(-) diff --git a/src/testing/setup.cairo b/src/testing/setup.cairo index f822676b..b880882d 100644 --- a/src/testing/setup.cairo +++ b/src/testing/setup.cairo @@ -1,42 +1,4 @@ use core::traits::Into; -#[starknet::contract] -mod MyToken { - use openzeppelin::token::erc20::ERC20Component; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>; - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>; - impl InternalImpl = ERC20Component::InternalImpl<ContractState>; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, fixed_supply: u256, recipient: ContractAddress) { - let name = 'MyToken'; - let symbol = 'MTK'; - - self.erc20.initializer(name, symbol); - self.erc20._mint(recipient, fixed_supply); - } -} - use array::ArrayTrait; use core::traits::TryInto; use debug::PrintTrait; @@ -46,6 +8,7 @@ use snforge_std::{ BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget }; + use governance::contract::IGovernanceDispatcher; use governance::contract::IGovernanceDispatcherTrait; use governance::proposals::IProposalsDispatcher; @@ -53,53 +16,57 @@ use governance::proposals::IProposalsDispatcherTrait; use governance::upgrades::IUpgradesDispatcher; use governance::upgrades::IUpgradesDispatcherTrait; use governance::constants; +use openzeppelin::token::erc20::interface::IERC20; use starknet::get_block_timestamp; const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; -const first_address: ContractAddress = 0x1.try_into().unwrap(); -const second_address: ContractAddress = 0x2.try_into().unwrap(); -const admin_addr: ContractAddress = 0x3.try_into().unwrap(); +const first_address: felt252 = 0x1; +const second_address: felt252 = 0x2; +const admin_addr: felt252 = 0x3; -fn deploy_governance() -> IGovernanceDispatcher { - let gov_contract = declare('Governance'); - let address = gov_contract.deploy().expect('unable to deploy governance'); - IGovernanceDispatcher { contract_address: address }; +fn deploy_governance(token_address: ContractAddress) -> IGovernanceDispatcher { + let gov_contract = declare("Governance"); + let mut args = ArrayTrait::new(); + args.append(token_address.into()); + let address = gov_contract.deploy(@args).expect('unable to deploy governance'); + IGovernanceDispatcher { contract_address: address } } -fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) { +fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) -> IERC20Dispatcher { let mut calldata = ArrayTrait::new(); calldata.append(GOV_TOKEN_INITIAL_SUPPLY); calldata.append(recipient.into()); - let gov_token_contract = declare('MyToken'); - let token_addr = gov_token_contract.deploy_at(@calldata).expect('unable to deploy MyToken'); + let gov_token_contract = declare("FloatingToken"); + let token_addr = gov_token_contract.deploy(@calldata).expect('unable to deploy FloatingToken'); let token: IERC20Dispatcher = IERC20Dispatcher { contract_address: token_addr }; - start_prank(CheatTarget::One(token_addr), admin_addr); + start_prank(CheatTarget::One(token_addr), admin_addr.try_into().unwrap()); - token.transfer(first_address, 100000); - token.transfer(second_address, 100000); + token.transfer(first_address.try_into().unwrap(), 100000); + token.transfer(second_address.try_into().unwrap(), 100000); + token } fn test_vote_upgrade_root(new_merkle_root: felt252) { - let gov_contract = deploy_governance(); + let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); + let gov_contract = deploy_governance(token_contract.contract_address); let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); let prop_id = dispatcher.submit_proposal(new_merkle_root, 3); - start_prank(CheatTarget::One(gov_contract_addr), first_address); + start_prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap()); dispatcher.vote(prop_id, 1); - start_prank(CheatTarget::One(gov_contract_addr), second_address); + start_prank(CheatTarget::One(gov_contract_addr), second_address.try_into().unwrap()); dispatcher.vote(prop_id, 1); - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); dispatcher.vote(prop_id, 1); assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); diff --git a/tests/lib.cairo b/tests/lib.cairo index b79504c6..ba630df1 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -1,5 +1,4 @@ mod add_options; mod basic; mod custom_proposals; -mod setup; mod test_treasury; From 6ed9c58623bce0f6241bd6cdfaf442794f5dea65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Tue, 30 Apr 2024 15:18:01 +0000 Subject: [PATCH 09/39] Polish tests --- tests/lib.cairo | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/lib.cairo b/tests/lib.cairo index ba630df1..e574f18a 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -1,4 +1,3 @@ mod add_options; mod basic; -mod custom_proposals; mod test_treasury; From 0ef0d6430997ec1a6e1fa780374814febba4e253 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Wed, 20 Mar 2024 19:29:27 +0000 Subject: [PATCH 10/39] Add airdrop tests --- tests/airdrop_tests.cairo | 99 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 tests/airdrop_tests.cairo diff --git a/tests/airdrop_tests.cairo b/tests/airdrop_tests.cairo new file mode 100644 index 00000000..d2483a7a --- /dev/null +++ b/tests/airdrop_tests.cairo @@ -0,0 +1,99 @@ +use core::hash::HashStateExTrait; +use core::{ArrayTrait, SpanTrait}; +use core::debug::PrintTrait; +use distributor::contract::{Distributor, IDistributorDispatcher, IDistributorDispatcherTrait}; +use Distributor::STRK_ADDRESS; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use snforge_std::{ContractClassTrait, declare, start_prank, CheatTarget}; +use starknet::{ContractAddress, deploy_syscall}; + +const ADMIN_ADDR: felt252 = 0x42; +const CLAIMEE_1: felt252 = 0x13; +const CLAIMEE_2: felt252 = 0x14; + +fn deploy() -> IDistributorDispatcher { + let mut calldata = ArrayTrait::new(); + calldata.append(ADMIN_ADDR); + + let contract = declare('Distributor'); + let address = contract.deploy(@calldata).expect('unable to deploy distributor'); + + IDistributorDispatcher { contract_address: address } +} + +fn deploy_token(recipient: ContractAddress) -> IERC20Dispatcher { + let mut calldata = ArrayTrait::new(); + calldata.append(1000000000000000000); + calldata.append(0); + calldata.append(recipient.into()); + let contract = declare('MyToken'); + let address = contract + .deploy_at(@calldata, STRK_ADDRESS.try_into().unwrap()) + .expect('unable to deploy mockstrk'); + + IERC20Dispatcher { contract_address: address } +} + +#[test] +fn test_claim_twice_with_same_proof() { + let contract = deploy(); + let tok = deploy_token(contract.contract_address); + + start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); + contract.add_root(valid_root); + + start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap()); + let initial_proof = array![valid_proof_element]; + contract.claim(valid_claim_amount, initial_proof.span()); + assert(tok.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "First claim failed"); + + + contract.claim(valid_claim_amount, initial_proof.span()); + assert(tok.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "Second claimed modified the claimee's balance"); +} + +#[test] +#[should_panic(expected: ('INVALID PROOF',))] +fn test_claim_invalid_proof() { + let contract = deploy(); + deploy_token(contract.contract_address); + start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); + contract.add_root(0xf7c8d3f309262572ad35df8ff6c33f24d8114c60eac3bc27bf42382ca82faf); + + start_prank( + CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap() + ); + let proof = array![ + 0x2a18afb0550a011d54ca3940648e59894c06e4c3d0a611256c0b575bd528b3b, + 0x1 + ]; + contract.claim(0x88, proof.span()); +} + +#[test] +fn test_update_root_and_claim_attempts() { + let contract = deploy(); + let tok = deploy_token(contract.contract_address); + start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); + + // add intial root and valid claim + contract.add_root(initial_root); + start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap()); + contract.claim(claim_amount, valid_proof_for_initial_root.span()); + assert(tok.balance_of(CLAIMEE_1.try_into().unwrap()) == claim_amount, 'initial claim failed'); + + // update root + start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); + contract.add_root(new_root); + + // claim with old root + new proof, should fail + start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_2.try_into().unwrap()); + contract.claim(claim_amount, new_proof_not_matching_old_root.span()); + // check fail : to do, use should panic ? + + // claim with new root + old proof, should fail + contract.claim(claim_amount, old_proof_not_matching_new_root.span()); + // check fail : to do +} + + From aa54ac26224f3cddc435ff09bcb2e1be44221594 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Mon, 25 Mar 2024 19:31:51 +0000 Subject: [PATCH 11/39] Adding setup file with generic function which applies a proposal to upgrade root and passes it --- src/airdrop.cairo | 2 +- tests/airdrop_tests.cairo | 41 ++++++++++--------- tests/setup.cairo | 86 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 21 deletions(-) create mode 100644 tests/setup.cairo diff --git a/src/airdrop.cairo b/src/airdrop.cairo index b9a934ff..0332d27e 100644 --- a/src/airdrop.cairo +++ b/src/airdrop.cairo @@ -28,7 +28,7 @@ mod airdrop { use governance::contract::Governance::ContractState; use governance::traits::IGovernanceTokenDispatcher; use governance::traits::IGovernanceTokenDispatcherTrait; - + #[storage] struct Storage { airdrop_claimed: LegacyMap::<ContractAddress, u128>, diff --git a/tests/airdrop_tests.cairo b/tests/airdrop_tests.cairo index d2483a7a..4eae2700 100644 --- a/tests/airdrop_tests.cairo +++ b/tests/airdrop_tests.cairo @@ -1,8 +1,8 @@ use core::hash::HashStateExTrait; use core::{ArrayTrait, SpanTrait}; use core::debug::PrintTrait; -use distributor::contract::{Distributor, IDistributorDispatcher, IDistributorDispatcherTrait}; -use Distributor::STRK_ADDRESS; +use governance::airdrop::{airdrop, IAirdropDispatcher, IAirdropDispatcherTrait}; +use airdrop::STRK_ADDRESS; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use snforge_std::{ContractClassTrait, declare, start_prank, CheatTarget}; use starknet::{ContractAddress, deploy_syscall}; @@ -11,16 +11,17 @@ const ADMIN_ADDR: felt252 = 0x42; const CLAIMEE_1: felt252 = 0x13; const CLAIMEE_2: felt252 = 0x14; -fn deploy() -> IDistributorDispatcher { + +fn deploy() -> IAirdropDispatcher { let mut calldata = ArrayTrait::new(); calldata.append(ADMIN_ADDR); - let contract = declare('Distributor'); - let address = contract.deploy(@calldata).expect('unable to deploy distributor'); - - IDistributorDispatcher { contract_address: address } + let contract = declare('Airdrop'); + let address = contract.deploy().expect('unable to deploy Airdrop'); + IAirdropDispatcher { contract_address: address } } + fn deploy_token(recipient: ContractAddress) -> IERC20Dispatcher { let mut calldata = ArrayTrait::new(); calldata.append(1000000000000000000); @@ -36,22 +37,22 @@ fn deploy_token(recipient: ContractAddress) -> IERC20Dispatcher { #[test] fn test_claim_twice_with_same_proof() { - let contract = deploy(); - let tok = deploy_token(contract.contract_address); - - start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); - contract.add_root(valid_root); - - start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap()); + let airdrop_contract = deploy(); + let token_contract = deploy_token(airdrop_contract.contract_address); + + start_prank(CheatTarget::One(airdrop_contract.contract_address), ADMIN_ADDR.try_into().unwrap()); + airdrop_contract.add_root(valid_root); + + start_prank(CheatTarget::One(airdrop_contract.contract_address), CLAIMEE_1.try_into().unwrap()); let initial_proof = array![valid_proof_element]; - contract.claim(valid_claim_amount, initial_proof.span()); - assert(tok.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "First claim failed"); - - - contract.claim(valid_claim_amount, initial_proof.span()); - assert(tok.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "Second claimed modified the claimee's balance"); + airdrop_contract.claim(CLAIMEE_1, valid_claim_amount, initial_proof.span()); + assert(token_contract.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "First claim failed"); + + airdrop_contract.claim(CLAIMEE_1, valid_claim_amount, initial_proof.span()); + assert(token_contract.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "Second claim modified the claimee's balance"); } + #[test] #[should_panic(expected: ('INVALID PROOF',))] fn test_claim_invalid_proof() { diff --git a/tests/setup.cairo b/tests/setup.cairo new file mode 100644 index 00000000..af276c86 --- /dev/null +++ b/tests/setup.cairo @@ -0,0 +1,86 @@ +use array::ArrayTrait; +use core::traits::TryInto; +use debug::PrintTrait; +use starknet::ContractAddress; +use snforge_std::{BlockId, declare, ContractClassTrait, ContractClass, start_prank, CheatTarget}; + +use governance::contract::IGovernanceDispatcher; +use governance::contract::IGovernanceDispatcherTrait; +use governance::proposals::IProposalsDispatcher; +use governance::proposals::IProposalsDispatcherTrait; +use governance::upgrades::IUpgradesDispatcher; +use governance::upgrades::IUpgradesDispatcherTrait; + +fn test_upgrade_root(new_merkle_root: felt) { + + let gov_contract_addr: ContractAddress = + 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f + .try_into() + .unwrap(); + + //let airdrop_contract_addr: ContractAddress = deploy_contract('Airdrop') + + let proposals_dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + let mut top_carm_holders = ArrayTrait::new(); + let marek_address: ContractAddress = + 0x0011d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233 + .try_into() + .unwrap(); + top_carm_holders.append(marek_address); + let scaling_address: ContractAddress = + 0x052df7acdfd3174241fa6bd5e1b7192cd133f8fc30a2a6ed99b0ddbfb5b22dcd + .try_into() + .unwrap(); + top_carm_holders.append(scaling_address); + let ondrej_address: ContractAddress = + 0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1 + .try_into() + .unwrap(); + top_carm_holders.append(ondrej_address); + let carlote_address: ContractAddress = + 0x021b2b25dd73bc60b0549683653081f8963562cbe5cba2d123ec0cbcbf0913e4 + .try_into() + .unwrap(); + top_carm_holders.append(carlote_address); + let fifth_address: ContractAddress = + 0x02af7135154dc27d9311b79c57ccc7b3a6ed74efd0c2b81116e8eb49dbf6aaf8 + .try_into() + .unwrap(); + top_carm_holders.append(fifth_address); + let sixth_address: ContractAddress = + 0x07824efd915baa421d93909bd7f24e36c022b5cfbc5af6687328848a6490ada7 + .try_into() + .unwrap(); + top_carm_holders.append(sixth_address); + let madman_address: ContractAddress = + 0x06717eaf502baac2b6b2c6ee3ac39b34a52e726a73905ed586e757158270a0af + .try_into() + .unwrap(); + top_carm_holders.append(madman_address); + let eighth_address: ContractAddress = + 0x03d1525605db970fa1724693404f5f64cba8af82ec4aab514e6ebd3dec4838ad + .try_into() + .unwrap(); + top_carm_holders.append(eighth_address); + + start_prank(CheatTarget::One(gov_contract_addr), scaling_address); + let new_prop_id = dispatcher.submit_proposal(new_merkle_root, 3); + + loop { + match top_carm_holders.pop_front() { + Option::Some(holder) => { + start_prank(CheatTarget::One(gov_contract_addr), holder); + dispatcher.vote(new_prop_id, 1); + }, + Option::None(()) => { break (); }, + } + }; + assert(dispatcher.get_proposal_status(new_prop_id) == 1, 'proposal not passed!'); + + let upgrade_dispatcher = IUpgradesDispatcher { contract_address: gov_contract_addr }; + upgrade_dispatcher.apply_passed_proposal(new_prop_id); + assert(check_if_healthy(gov_contract_addr), 'new gov not healthy'); + +} + From 7f32f99c004df31fee78d0863294eba1a7e2fbf5 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Tue, 16 Apr 2024 18:03:22 +0000 Subject: [PATCH 12/39] Setup environment to deploy governance, deploy gov token and distribute to sample addresses and then vote on update root proposal --- tests/setup.cairo | 155 ++++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 68 deletions(-) diff --git a/tests/setup.cairo b/tests/setup.cairo index af276c86..f4a109a9 100644 --- a/tests/setup.cairo +++ b/tests/setup.cairo @@ -1,7 +1,46 @@ +#[starknet::contract] +mod MyToken { + use openzeppelin::token::erc20::ERC20Component; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>; + impl InternalImpl = ERC20Component::InternalImpl<ContractState>; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, fixed_supply: u256, recipient: ContractAddress) { + let name = 'MyToken'; + let symbol = 'MTK'; + + self.erc20.initializer(name, symbol); + self.erc20._mint(recipient, fixed_supply); + } +} + use array::ArrayTrait; use core::traits::TryInto; use debug::PrintTrait; use starknet::ContractAddress; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use snforge_std::{BlockId, declare, ContractClassTrait, ContractClass, start_prank, CheatTarget}; use governance::contract::IGovernanceDispatcher; @@ -11,76 +50,56 @@ use governance::proposals::IProposalsDispatcherTrait; use governance::upgrades::IUpgradesDispatcher; use governance::upgrades::IUpgradesDispatcherTrait; -fn test_upgrade_root(new_merkle_root: felt) { - - let gov_contract_addr: ContractAddress = - 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f - .try_into() - .unwrap(); - - //let airdrop_contract_addr: ContractAddress = deploy_contract('Airdrop') - - let proposals_dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - let mut top_carm_holders = ArrayTrait::new(); - let marek_address: ContractAddress = - 0x0011d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233 - .try_into() - .unwrap(); - top_carm_holders.append(marek_address); - let scaling_address: ContractAddress = - 0x052df7acdfd3174241fa6bd5e1b7192cd133f8fc30a2a6ed99b0ddbfb5b22dcd - .try_into() - .unwrap(); - top_carm_holders.append(scaling_address); - let ondrej_address: ContractAddress = - 0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1 - .try_into() - .unwrap(); - top_carm_holders.append(ondrej_address); - let carlote_address: ContractAddress = - 0x021b2b25dd73bc60b0549683653081f8963562cbe5cba2d123ec0cbcbf0913e4 - .try_into() - .unwrap(); - top_carm_holders.append(carlote_address); - let fifth_address: ContractAddress = - 0x02af7135154dc27d9311b79c57ccc7b3a6ed74efd0c2b81116e8eb49dbf6aaf8 - .try_into() - .unwrap(); - top_carm_holders.append(fifth_address); - let sixth_address: ContractAddress = - 0x07824efd915baa421d93909bd7f24e36c022b5cfbc5af6687328848a6490ada7 - .try_into() - .unwrap(); - top_carm_holders.append(sixth_address); - let madman_address: ContractAddress = - 0x06717eaf502baac2b6b2c6ee3ac39b34a52e726a73905ed586e757158270a0af - .try_into() - .unwrap(); - top_carm_holders.append(madman_address); - let eighth_address: ContractAddress = - 0x03d1525605db970fa1724693404f5f64cba8af82ec4aab514e6ebd3dec4838ad - .try_into() - .unwrap(); - top_carm_holders.append(eighth_address); - - start_prank(CheatTarget::One(gov_contract_addr), scaling_address); - let new_prop_id = dispatcher.submit_proposal(new_merkle_root, 3); - - loop { - match top_carm_holders.pop_front() { - Option::Some(holder) => { - start_prank(CheatTarget::One(gov_contract_addr), holder); - dispatcher.vote(new_prop_id, 1); - }, - Option::None(()) => { break (); }, - } - }; - assert(dispatcher.get_proposal_status(new_prop_id) == 1, 'proposal not passed!'); +const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; + +const first_address: ContractAddress = 0x1.try_into().unwrap(); +const second_address: ContractAddress = 0x2.try_into().unwrap(); +const admin_addr: ContractAddress = 0x3.try_into().unwrap(); + +fn deploy_governance() -> IGovernanceDispatcher { + let gov_contract = declare('Governance'); + let address = gov_contract.deploy().expect('unable to deploy governance'); + IGovernanceDispatcher { contract_address: address }; +} + + +fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) { + let mut calldata = ArrayTrait::new(); + calldata.append(GOV_TOKEN_INITIAL_SUPPLY); + calldata.append(recipient); + + let gov_token_contract = declare('MyToken'); + let token_addr = gov_token_contract.deploy_at(@calldata).expect('unable to deploy MyToken'); + let token: IERC20Dispatcher = IERC20Dispatcher { contract_address: token_addr }; + + start_prank(CheatTarget::One(token_addr), admin_addr); + + token.transfer(first_address, 100000); + token.transfer(second_address, 100000); +} + + +fn test_vote_upgrade_root(new_merkle_root: felt252) { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(new_merkle_root, 3); + + start_prank(CheatTarget::One(gov_contract_addr), first_address); + dispatcher.vote(prop_id, 1); + start_prank(CheatTarget::One(gov_contract_addr), second_address); + dispatcher.vote(prop_id, 1); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + dispatcher.vote(prop_id, 1); + + assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); let upgrade_dispatcher = IUpgradesDispatcher { contract_address: gov_contract_addr }; - upgrade_dispatcher.apply_passed_proposal(new_prop_id); + upgrade_dispatcher.apply_passed_proposal(prop_id); assert(check_if_healthy(gov_contract_addr), 'new gov not healthy'); - } From a2e7bfa2ca72b4c2fa0dc84b833ef285588269e1 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Fri, 26 Apr 2024 15:53:21 +0000 Subject: [PATCH 13/39] Add tests on proposals --- tests/setup.cairo | 61 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/tests/setup.cairo b/tests/setup.cairo index f4a109a9..9795e622 100644 --- a/tests/setup.cairo +++ b/tests/setup.cairo @@ -41,7 +41,9 @@ use core::traits::TryInto; use debug::PrintTrait; use starknet::ContractAddress; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use snforge_std::{BlockId, declare, ContractClassTrait, ContractClass, start_prank, CheatTarget}; +use snforge_std::{ + BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget +}; use governance::contract::IGovernanceDispatcher; use governance::contract::IGovernanceDispatcherTrait; @@ -49,6 +51,9 @@ use governance::proposals::IProposalsDispatcher; use governance::proposals::IProposalsDispatcherTrait; use governance::upgrades::IUpgradesDispatcher; use governance::upgrades::IUpgradesDispatcherTrait; +use governance::constants; +use starknet::get_block_timestamp; + const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; @@ -103,3 +108,57 @@ fn test_vote_upgrade_root(new_merkle_root: felt252) { assert(check_if_healthy(gov_contract_addr), 'new gov not healthy'); } + +fn test_express_proposal() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + dispatcher.vote(prop_id, 1); + + assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); +} + +#[should_panic] +fn test_proposal_expiry() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + start_warp(current_timestamp, end_timestamp + 1); + + let status = dispatcher.get_proposal_status(prop_id); +} + +#[should_panic] +fn test_vote_on_expired_proposal() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + start_warp(current_timestamp, end_timestamp + 1); + + start_prank(CheatTarget::One(gov_contract_addr), first_address); + dispatcher.vote(prop_id, 1); +} + From 3f5f10de6ef88c0ecacb9628bb068d5bd303b80d Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Fri, 26 Apr 2024 16:02:59 +0000 Subject: [PATCH 14/39] fix some issues on proposal tests --- tests/setup.cairo | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/setup.cairo b/tests/setup.cairo index 9795e622..7d240631 100644 --- a/tests/setup.cairo +++ b/tests/setup.cairo @@ -1,3 +1,4 @@ +use core::traits::Into; #[starknet::contract] mod MyToken { use openzeppelin::token::erc20::ERC20Component; @@ -71,7 +72,7 @@ fn deploy_governance() -> IGovernanceDispatcher { fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) { let mut calldata = ArrayTrait::new(); calldata.append(GOV_TOKEN_INITIAL_SUPPLY); - calldata.append(recipient); + calldata.append(recipient.into()); let gov_token_contract = declare('MyToken'); let token_addr = gov_token_contract.deploy_at(@calldata).expect('unable to deploy MyToken'); @@ -108,6 +109,14 @@ fn test_vote_upgrade_root(new_merkle_root: felt252) { assert(check_if_healthy(gov_contract_addr), 'new gov not healthy'); } +fn check_if_healthy(gov_contract_addr: ContractAddress) -> bool { + // TODO + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + dispatcher.get_proposal_status(0); + let prop_details = dispatcher.get_proposal_details(0); + (prop_details.payload + prop_details.to_upgrade) != 0 +} + fn test_express_proposal() { let gov_contract = deploy_governance(); @@ -136,9 +145,10 @@ fn test_proposal_expiry() { start_prank(CheatTarget::One(gov_contract_addr), admin_addr); let prop_id = dispatcher.submit_proposal(42, 1); + //simulate passage of time let current_timestamp = get_block_timestamp(); let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(current_timestamp, end_timestamp + 1); + start_warp(end_timestamp + 1, current_timestamp); let status = dispatcher.get_proposal_status(prop_id); } @@ -154,9 +164,10 @@ fn test_vote_on_expired_proposal() { start_prank(CheatTarget::One(gov_contract_addr), admin_addr); let prop_id = dispatcher.submit_proposal(42, 1); + //simulate passage of time let current_timestamp = get_block_timestamp(); let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(current_timestamp, end_timestamp + 1); + start_warp(end_timestamp + 1, current_timestamp); start_prank(CheatTarget::One(gov_contract_addr), first_address); dispatcher.vote(prop_id, 1); From b944b099d2f92329110831a58fb989ee492fcf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hobza?= <hobza.tomas@gmail.com> Date: Tue, 30 Apr 2024 09:51:37 +0200 Subject: [PATCH 15/39] Proposals Frontend (#66) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add: basic ui displaying proposals * feat: voting invocations * feat: :sparkles: new proposal form * feat: :sparkles: use async for proposal creation * fix: :bug: bad voting code * chore: :wastebasket: cleanup * feat: :sparkles: add logo * fix: :bug: wrong site title --------- Co-authored-by: Tomáš Hobza <xhobza03@vutbr.cz> --- frontend/.eslintrc.cjs | 29 + frontend/.eslintrc.json | 17 + frontend/.gitignore | 24 + frontend/index.html | 13 + frontend/package-lock.json | 6398 +++++++++++++++++ frontend/package.json | 35 + frontend/postcss.config.cjs | 6 + frontend/public/vite.svg | 1 + frontend/src/App.tsx | 99 + frontend/src/api/index.ts | 27 + frontend/src/components/Header.tsx | 32 + frontend/src/components/NewProposalForm.tsx | 89 + frontend/src/components/Proposal.tsx | 117 + .../src/components/starknet/ConnectModal.tsx | 34 + frontend/src/components/ui/Button.tsx | 16 + frontend/src/components/ui/Dialog.tsx | 32 + frontend/src/constants/amm.ts | 74 + frontend/src/constants/config.json | 18 + frontend/src/globals.css | 20 + frontend/src/lib/abi.ts | 411 ++ frontend/src/lib/config.ts | 2 + frontend/src/main.tsx | 63 + frontend/src/vite-env.d.ts | 1 + frontend/tailwind.config.js | 8 + frontend/tsconfig.json | 21 + frontend/tsconfig.node.json | 9 + frontend/vite.config.ts | 16 + 27 files changed, 7612 insertions(+) create mode 100644 frontend/.eslintrc.cjs create mode 100644 frontend/.eslintrc.json create mode 100644 frontend/.gitignore create mode 100644 frontend/index.html create mode 100644 frontend/package-lock.json create mode 100644 frontend/package.json create mode 100644 frontend/postcss.config.cjs create mode 100644 frontend/public/vite.svg create mode 100644 frontend/src/App.tsx create mode 100644 frontend/src/api/index.ts create mode 100644 frontend/src/components/Header.tsx create mode 100644 frontend/src/components/NewProposalForm.tsx create mode 100644 frontend/src/components/Proposal.tsx create mode 100644 frontend/src/components/starknet/ConnectModal.tsx create mode 100644 frontend/src/components/ui/Button.tsx create mode 100644 frontend/src/components/ui/Dialog.tsx create mode 100644 frontend/src/constants/amm.ts create mode 100644 frontend/src/constants/config.json create mode 100644 frontend/src/globals.css create mode 100644 frontend/src/lib/abi.ts create mode 100644 frontend/src/lib/config.ts create mode 100644 frontend/src/main.tsx create mode 100644 frontend/src/vite-env.d.ts create mode 100644 frontend/tailwind.config.js create mode 100644 frontend/tsconfig.json create mode 100644 frontend/tsconfig.node.json create mode 100644 frontend/vite.config.ts diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs new file mode 100644 index 00000000..5d94793c --- /dev/null +++ b/frontend/.eslintrc.cjs @@ -0,0 +1,29 @@ +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react/recommended", + ], + overrides: [ + { + env: { + node: true, + }, + files: [".eslintrc.{js,cjs}"], + parserOptions: { + sourceType: "script", + }, + }, + ], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + }, + plugins: ["@typescript-eslint", "react"], + rules: {}, +}; diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json new file mode 100644 index 00000000..7b49ed51 --- /dev/null +++ b/frontend/.eslintrc.json @@ -0,0 +1,17 @@ +{ + "env": { + "browser": true, + "es2021": true + }, + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "overrides": [], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "project": "./tsconfig.json", + "sourceType": "module" + }, + "plugins": ["react", "@typescript-eslint"], + "root": true, + "rules": {} +} diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 00000000..4fd26963 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <link rel="icon" type="image/svg+xml" href="/vite.svg" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Konoha Governance</title> + </head> + <body> + <div id="root"></div> + <script type="module" src="/src/main.tsx"></script> + </body> +</html> diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 00000000..3903aa43 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,6398 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "dependencies": { + "@starknet-react/chains": "^0.1.0", + "@starknet-react/core": "^2.1.0", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "get-starknet-core": "^3.2.0", + "next": "^14.0.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", + "starknet": "^5.25.0", + "tailwindcss": "^3.3.5" + }, + "devDependencies": { + "@types/react": "^18.0.27", + "@types/react-dom": "^18.0.10", + "@vitejs/plugin-react": "^3.1.0", + "autoprefixer": "^10.4.16", + "eslint": "8.33.0", + "eslint-plugin-react": "^7.31.4", + "postcss": "^8.4.31", + "typescript": "4.9.5", + "vite": "^4.1.0", + "vite-plugin-checker": "^0.5.1" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", + "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz", + "integrity": "sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@module-federation/runtime": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.1.10.tgz", + "integrity": "sha512-Oiu+a394whgOulfO2FTlSGDyckdYXaIUEA6KaLonKoaWwEFgwO+EaiL8zaMvO2WztUvpU+Apir+fUuVsyuSMzA==", + "dependencies": { + "@module-federation/sdk": "0.1.10" + } + }, + "node_modules/@module-federation/sdk": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.1.10.tgz", + "integrity": "sha512-HzRGtt+S45Hzg43tTBxu1lf2Zo8z7slf9S9Q4lN9knfz5ho1IGoQ+Ig6+UI1JYmheuaHOOxz6nVyPx9QzZEREg==" + }, + "node_modules/@next/env": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz", + "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", + "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz", + "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz", + "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz", + "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz", + "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", + "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", + "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", + "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", + "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rometools/cli-darwin-arm64": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/@rometools/cli-darwin-arm64/-/cli-darwin-arm64-12.1.3.tgz", + "integrity": "sha512-AmFTUDYjBuEGQp/Wwps+2cqUr+qhR7gyXAUnkL5psCuNCz3807TrUq/ecOoct5MIavGJTH6R4aaSL6+f+VlBEg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rometools/cli-darwin-x64": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/@rometools/cli-darwin-x64/-/cli-darwin-x64-12.1.3.tgz", + "integrity": "sha512-k8MbWna8q4LRlb005N2X+JS1UQ+s3ZLBBvwk4fP8TBxlAJXUz17jLLu/Fi+7DTTEmMhM84TWj4FDKW+rNar28g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rometools/cli-linux-arm64": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/@rometools/cli-linux-arm64/-/cli-linux-arm64-12.1.3.tgz", + "integrity": "sha512-X/uLhJ2/FNA3nu5TiyeNPqiD3OZoFfNfRvw6a3ut0jEREPvEn72NI7WPijH/gxSz55znfQ7UQ6iM4DZumUknJg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rometools/cli-linux-x64": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/@rometools/cli-linux-x64/-/cli-linux-x64-12.1.3.tgz", + "integrity": "sha512-csP17q1eWiUXx9z6Jr/JJPibkplyKIwiWPYNzvPCGE8pHlKhwZj3YHRuu7Dm/4EOqx0XFIuqqWZUYm9bkIC8xg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rometools/cli-win32-arm64": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/@rometools/cli-win32-arm64/-/cli-win32-arm64-12.1.3.tgz", + "integrity": "sha512-RymHWeod57EBOJY4P636CgUwYA6BQdkQjh56XKk4pLEHO6X1bFyMet2XL7KlHw5qOTalzuzf5jJqUs+vf3jdXQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rometools/cli-win32-x64": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/@rometools/cli-win32-x64/-/cli-win32-x64-12.1.3.tgz", + "integrity": "sha512-yHSKYidqJMV9nADqg78GYA+cZ0hS1twANAjiFibQdXj9aGzD+s/IzIFEIi/U/OBLvWYg/SCw0QVozi2vTlKFDQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scure/base": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/starknet": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@scure/starknet/-/starknet-1.0.0.tgz", + "integrity": "sha512-o5J57zY0f+2IL/mq8+AYJJ4Xpc1fOtDhr+mFQKbHnYFmm3WQrC+8zj2HEgxak1a+x86mhmBC1Kq305KUpVf0wg==", + "dependencies": { + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@starknet-react/chains": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@starknet-react/chains/-/chains-0.1.7.tgz", + "integrity": "sha512-UNh97I1SvuJKaAhKOmpEk8JcWuZWMlPG/ba2HcvFYL9x/47BKndJ+Da9V+iJFtkHUjreVnajT1snsaz1XMG+UQ==" + }, + "node_modules/@starknet-react/core": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@starknet-react/core/-/core-2.6.1.tgz", + "integrity": "sha512-EaHT/B/If2PC0CVlb8Wwdv5axmmIRK+ysjTUbSeIs7/U8A03KXuuoJBrXMHLPBgMWk/0E0hZKqNUVdDKGVlFTQ==", + "dependencies": { + "@starknet-react/chains": "^0.1.7", + "@tanstack/react-query": "^5.0.1", + "eventemitter3": "^5.0.1", + "immutable": "^4.3.4", + "zod": "^3.22.2" + }, + "peerDependencies": { + "get-starknet-core": "^3.2.0", + "react": "^18.0", + "starknet": "^5.25.0" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.32.0.tgz", + "integrity": "sha512-Z3flEgCat55DRXU5UMwYU1U+DgFZKA3iufyOKs+II7iRAo0uXkeU7PH5e6sOH1CGEag0IpKmZxlUFpCg6roSKw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.32.0.tgz", + "integrity": "sha512-+E3UudQtarnx9A6xhpgMZapyF+aJfNBGFMgI459FnduEZqT/9KhOWnMOneZahLRt52yzskSA0AuOyLkXHK0yBA==", + "dependencies": { + "@tanstack/query-core": "5.32.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.0.tgz", + "integrity": "sha512-DiUcKjzE6soLyln8NNZmyhcQjVv+WsUIFSqetMN0p8927OztKT4VTfFTqsbAi5oAGIcgOmOajlfBqyptDDjZRw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz", + "integrity": "sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==", + "dev": true, + "dependencies": { + "@babel/core": "^7.20.12", + "@babel/plugin-transform-react-jsx-self": "^7.18.6", + "@babel/plugin-transform-react-jsx-source": "^7.19.6", + "magic-string": "^0.27.0", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.1.0-beta.0" + } + }, + "node_modules/abi-wan-kanabi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/abi-wan-kanabi/-/abi-wan-kanabi-1.0.3.tgz", + "integrity": "sha512-Xwva0AnhXx/IVlzo3/kwkI7Oa7ZX7codtcSn+Gmoa2PmjGPF/0jeVud9puasIPtB7V50+uBdUj4Mh3iATqtBvg==", + "dependencies": { + "abi-wan-kanabi": "^1.0.1", + "fs-extra": "^10.0.0", + "rome": "^12.1.3", + "typescript": "^4.9.5", + "yargs": "^17.7.2" + }, + "bin": { + "generate": "dist/generate.js" + } + }, + "node_modules/abi-wan-kanabi-v1": { + "name": "abi-wan-kanabi", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/abi-wan-kanabi/-/abi-wan-kanabi-1.0.3.tgz", + "integrity": "sha512-Xwva0AnhXx/IVlzo3/kwkI7Oa7ZX7codtcSn+Gmoa2PmjGPF/0jeVud9puasIPtB7V50+uBdUj4Mh3iATqtBvg==", + "dependencies": { + "abi-wan-kanabi": "^1.0.1", + "fs-extra": "^10.0.0", + "rome": "^12.1.3", + "typescript": "^4.9.5", + "yargs": "^17.7.2" + }, + "bin": { + "generate": "dist/generate.js" + } + }, + "node_modules/abi-wan-kanabi-v2": { + "name": "abi-wan-kanabi", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/abi-wan-kanabi/-/abi-wan-kanabi-2.2.2.tgz", + "integrity": "sha512-sTCv2HyNIj1x2WFUoc9oL8ZT9liosrL+GoqEGZJK1kDND096CfA7lwx06vLxLWMocQ41FQXO3oliwoh/UZHYdQ==", + "dependencies": { + "ansicolors": "^0.3.2", + "cardinal": "^2.1.1", + "fs-extra": "^10.0.0", + "yargs": "^17.7.2" + }, + "bin": { + "generate": "dist/generate.js" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==" + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "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" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001612", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", + "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.749", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.749.tgz", + "integrity": "sha512-LRMMrM9ITOvue0PoBrvNIraVmuDbJV5QC9ierz/z5VilMdPOVMjOtpICNld3PuXuTZ3CHH/UPxX9gHhAPwi+0Q==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", + "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", + "dependencies": { + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-starknet-core": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/get-starknet-core/-/get-starknet-core-3.3.0.tgz", + "integrity": "sha512-TG17zIBdjHIyO0CTjkB7lkuvo24OHLrkB/rZSEdspEAcwcysMpZOVgwrNPIzD89kU8gZ3m1UANarFNPVLULS5Q==", + "dependencies": { + "@module-federation/runtime": "^0.1.2" + }, + "peerDependencies": { + "starknet": "^5.18.0" + }, + "peerDependenciesMeta": { + "starknet": { + "optional": false + } + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/goober": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", + "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-sdsl": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", + "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lossless-json": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-2.0.11.tgz", + "integrity": "sha512-BP0vn+NGYvzDielvBZaFain/wgeJ1hTvURCqtKvhr1SCPePdaaTanmmcplrHfEJSJOUql7hk4FHwToNJjWRY3g==" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/next": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz", + "integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==", + "dependencies": { + "@next/env": "14.2.3", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.3", + "@next/swc-darwin-x64": "14.2.3", + "@next/swc-linux-arm64-gnu": "14.2.3", + "@next/swc-linux-arm64-musl": "14.2.3", + "@next/swc-linux-x64-gnu": "14.2.3", + "@next/swc-linux-x64-musl": "14.2.3", + "@next/swc-win32-arm64-msvc": "14.2.3", + "@next/swc-win32-ia32-msvc": "14.2.3", + "@next/swc-win32-x64-msvc": "14.2.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.1.tgz", + "integrity": "sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.0.tgz", + "integrity": "sha512-RPutkJftSAldDibyrjuku7q11d3oy6wKOyPe5K1HA/HwwrXcEqBdHsLypkC2FFYjP7bPUa6gbzSBhw4sY2JcDg==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-zaKdLBftQJnvb7FtDIpZtsAIb2MZU087RM8bRDZU8LVCCFYjPTsDZJNFUWPcVz3HFSN1n/caxi0ca4B/aaVQGQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.1" + }, + "peerDependencies": { + "react": "^18.3.0" + } + }, + "node_modules/react-hot-toast": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", + "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", + "dependencies": { + "goober": "^2.1.10" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/react-refresh": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.1.tgz", + "integrity": "sha512-iZiRCtNGY3QYP3pYOSSBOvQmBpQTcJccr/VcK2blpJrpPTUDjeN51mxm5nsrkCzBwsbGUj+TN9q2oPz5E13FLg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rome": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/rome/-/rome-12.1.3.tgz", + "integrity": "sha512-e+ff72hxDpe/t5/Us7YRBVw3PBET7SeczTQNn6tvrWdrCaAw3qOukQQ+tDCkyFtS4yGsnhjrJbm43ctNbz27Yg==", + "hasInstallScript": true, + "bin": { + "rome": "bin/rome" + }, + "engines": { + "node": ">=14.*" + }, + "optionalDependencies": { + "@rometools/cli-darwin-arm64": "12.1.3", + "@rometools/cli-darwin-x64": "12.1.3", + "@rometools/cli-linux-arm64": "12.1.3", + "@rometools/cli-linux-x64": "12.1.3", + "@rometools/cli-win32-arm64": "12.1.3", + "@rometools/cli-win32-x64": "12.1.3" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.1.tgz", + "integrity": "sha512-5GKS5JGfiah1O38Vfa9srZE4s3wdHbwjlCrvIookrg2FO9aIwKLOJXuJQFlEfNcVSOXuaL2hzDeY20uVXcUtrw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/starknet": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/starknet/-/starknet-5.29.0.tgz", + "integrity": "sha512-eEcd6uiYIwGvl8MtHOsXGBhREqjJk84M/qUkvPLQ3n/JAMkbKBGnygDlh+HAsvXJsGlMQfwrcVlm6KpDoPha7w==", + "dependencies": { + "@noble/curves": "~1.3.0", + "@scure/base": "~1.1.3", + "@scure/starknet": "~1.0.0", + "abi-wan-kanabi-v1": "npm:abi-wan-kanabi@^1.0.3", + "abi-wan-kanabi-v2": "npm:abi-wan-kanabi@^2.1.1", + "isomorphic-fetch": "^3.0.0", + "lossless-json": "^2.0.8", + "pako": "^2.0.4", + "url-join": "^4.0.1" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", + "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/vite": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "dev": true, + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.5.6.tgz", + "integrity": "sha512-ftRyON0gORUHDxcDt2BErmsikKSkfvl1i2DoP6Jt2zDO9InfvM6tqO1RkXhSjkaXEhKPea6YOnhFaZxW3BzudQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "ansi-escapes": "^4.3.0", + "chalk": "^4.1.1", + "chokidar": "^3.5.1", + "commander": "^8.0.0", + "fast-glob": "^3.2.7", + "fs-extra": "^11.1.0", + "lodash.debounce": "^4.0.8", + "lodash.pick": "^4.4.0", + "npm-run-path": "^4.0.1", + "strip-ansi": "^6.0.0", + "tiny-invariant": "^1.1.0", + "vscode-languageclient": "^7.0.0", + "vscode-languageserver": "^7.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-uri": "^3.0.2" + }, + "engines": { + "node": ">=14.16" + }, + "peerDependencies": { + "eslint": ">=7", + "meow": "^9.0.0", + "optionator": "^0.9.1", + "stylelint": ">=13", + "typescript": "*", + "vite": ">=2.0.0", + "vls": "*", + "vti": "*", + "vue-tsc": "*" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "meow": { + "optional": true + }, + "optionator": { + "optional": true + }, + "stylelint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vls": { + "optional": true + }, + "vti": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/vite-plugin-checker/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/vite-plugin-checker/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/vite-plugin-checker/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/vite-plugin-checker/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/vite-plugin-checker/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/vite-plugin-checker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/vite-plugin-checker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", + "dev": true, + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4", + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" + }, + "engines": { + "vscode": "^1.52.0" + } + }, + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/vscode-languageserver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", + "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", + "dev": true, + "dependencies": { + "vscode-languageserver-protocol": "3.16.0" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "dev": true, + "dependencies": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", + "dev": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", + "dev": true + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.23.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.4.tgz", + "integrity": "sha512-/AtWOKbBgjzEYYQRNfoGKHObgfAZag6qUJX1VbHo2PRBgS+wfWagEY2mizjfyAPcGesrJOcx/wcl0L9WnVrHFw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 00000000..896460fd --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,35 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@starknet-react/chains": "^0.1.0", + "@starknet-react/core": "^2.1.0", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "get-starknet-core": "^3.2.0", + "next": "^14.0.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", + "starknet": "^5.25.0", + "tailwindcss": "^3.3.5" + }, + "devDependencies": { + "@types/react": "^18.0.27", + "@types/react-dom": "^18.0.10", + "@vitejs/plugin-react": "^3.1.0", + "autoprefixer": "^10.4.16", + "eslint": "8.33.0", + "eslint-plugin-react": "^7.31.4", + "postcss": "^8.4.31", + "typescript": "4.9.5", + "vite": "^4.1.0", + "vite-plugin-checker": "^0.5.1" + } +} diff --git a/frontend/postcss.config.cjs b/frontend/postcss.config.cjs new file mode 100644 index 00000000..12a703d9 --- /dev/null +++ b/frontend/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/frontend/public/vite.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg> \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 00000000..f626e574 --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,99 @@ +import React from "react"; +// import { useBlock } from "@starknet-react/core"; +import Header from "./components/Header"; +import { useContractRead } from "@starknet-react/core"; +import { abi } from "./lib/abi"; +import Proposal from "./components/Proposal"; +import { CONTRACT_ADDR } from "./lib/config"; +import NewProposalForm from "./components/NewProposalForm"; +// import { useAccount } from "@starknet-react/core"; + +function App() { + const [isModalOpen, setIsModalOpen] = React.useState(false); + + // Call the contract function get_live_proposals to get the live proposals + const { data, isError, isLoading, error } = useContractRead({ + functionName: "get_live_proposals", + args: [], + abi, + address: CONTRACT_ADDR, + watch: true, + }); + + // Check if there is an error, if there is, display the error message + if (isError) { + return <div>{error?.message}</div>; + } + + // Display the proposals + return ( + <main className="flex flex-col items-center min-h-screen gap-12 mt-16"> + <Header /> + {isModalOpen && ( + <dialog className="fixed inset-0 z-50 flex items-center justify-center w-full h-full p-6 bg-black bg-opacity-50"> + <div className="relative flex flex-col items-center gap-4 p-8 bg-white rounded-lg"> + {/* Close modal button */} + <button + className="absolute right-3 top-3 text-slate-400" + onClick={() => setIsModalOpen(false)} + > + <svg + xmlns="http://www.w3.org/2000/svg" + className="w-6 h-6" + fill="none" + viewBox="0 0 24 24" + stroke="currentColor" + > + <path + strokeLinecap="round" + strokeLinejoin="round" + strokeWidth={2} + d="M6 18L18 6M6 6l12 12" + /> + </svg> + </button> + <p className="text-xl font-bold">New proposal</p> + {/* New proposal form */} + <NewProposalForm setIsModalOpen={setIsModalOpen} /> + </div> + </dialog> + )} + + {/* List of proposals */} + <div className="flex max-w-[50rem] flex-col items-center w-full gap-2 p-6"> + <div className="flex flex-row items-start w-full"> + <div className="flex-grow text-2xl font-bold"> + Proposals + </div> + + {/* New proposal button */} + <button + className="px-3 py-2 text-sm font-semibold text-blue-500 transition-all rounded-lg hover:bg-slate-200" + onClick={() => setIsModalOpen(true)} + > + + New Proposal + </button> + </div> + <div className="max-w-[50rem] w-full text-sm text-slate-300"> + It may take a few seconds for new proposals to appear here + after they are submitted. + </div> + {isLoading ? ( + <div className="text-center">loading...</div> + ) : ( + (data as bigint[])?.map((proposal, index: number) => { + return ( + <Proposal + key={index} + proposalId={proposal} + index={index} + /> + ); + }) + )} + </div> + </main> + ); +} + +export default App; diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts new file mode 100644 index 00000000..713b774d --- /dev/null +++ b/frontend/src/api/index.ts @@ -0,0 +1,27 @@ +import { API_URL, NETWORK } from "../constants/amm"; + +export type ApiConfig = { + network?: "testnet" | "mainnet"; + version?: 1 | 2; +}; + +export const apiUrl = (path: string, config?: ApiConfig): string => { + if (!path) { + throw Error("Cannot query empty path"); + } + + const DEFAULT_CONFIG = { network: NETWORK, version: 1 }; + + const finalConfig = { ...DEFAULT_CONFIG, ...(config || {}) }; + + const base = new URL(API_URL); + + // avoid double slashes // + const validatedPath = path.charAt(0) === "/" ? path.slice(1) : path; + + const finalPath = `/api/v${finalConfig.version}/${finalConfig.network}/${validatedPath}`; + + const url = new URL(finalPath, base); + + return url.toString(); +}; diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx new file mode 100644 index 00000000..012ec7af --- /dev/null +++ b/frontend/src/components/Header.tsx @@ -0,0 +1,32 @@ +import { useAccount, useDisconnect } from "@starknet-react/core"; +import React from "react"; +import ConnectModal from "./starknet/ConnectModal"; + +export default function Header() { + const { address } = useAccount(); + const { disconnect } = useDisconnect(); + + return ( + <div className="fixed top-0 left-0 right-0 flex flex-row items-center justify-between p-2 px-4 bg-white border "> + <div className="flex flex-row items-center flex-grow gap-2 text-xl"> + <div>🏡</div> <div>Konoha</div> + </div> + {address ? ( + <div className="flex flex-col items-end px-6 py-2 rounded-md bg-zinc-100"> + <p className="font-semibold">{`${address.slice( + 0, + 6 + )}...${address.slice(-4)}`}</p> + <p + onClick={() => disconnect()} + className="cursor-pointer text-black/50" + > + Disconnect + </p> + </div> + ) : ( + <ConnectModal /> + )} + </div> + ); +} diff --git a/frontend/src/components/NewProposalForm.tsx b/frontend/src/components/NewProposalForm.tsx new file mode 100644 index 00000000..7e3e797d --- /dev/null +++ b/frontend/src/components/NewProposalForm.tsx @@ -0,0 +1,89 @@ +import React, { useMemo } from "react"; +import toast from "react-hot-toast"; +import { CONTRACT_ADDR } from "../lib/config"; +import { useAccount, useContractWrite } from "@starknet-react/core"; + +export default function NewProposalForm({ + setIsModalOpen, +}: { + setIsModalOpen: React.Dispatch<React.SetStateAction<boolean>>; +}) { + const { isConnected } = useAccount(); + + // State variables for the payload and to_upgrade + const [payload, setPayload] = React.useState<string>(""); + const [to_upgrade, setToUpgrade] = React.useState<string>(""); + + // Create a call to submit a proposal + const calls = useMemo(() => { + const tx = { + contractAddress: CONTRACT_ADDR, + entrypoint: "submit_proposal", + calldata: [payload.toString(), to_upgrade.toString()], + }; + return [tx]; + }, [payload, to_upgrade, submitProposal]); + + // Use the useContractWrite hook to write the proposal + const { writeAsync } = useContractWrite({ calls }); + + function submitProposal(e: React.FormEvent<HTMLFormElement>) { + e.preventDefault(); + + // Check if the user is connected + if (!isConnected) { + toast.error("Please connect your wallet"); + return; + } + + // Check if the payload and to_upgrade fields are filled out + if (!payload || !to_upgrade) { + toast.error("Please fill out all fields"); + return; + } + + // Call the write function to submit the proposal + writeAsync() + .then(() => { + toast.success("Proposal submitted"); + setIsModalOpen(false); + }) + .catch((e) => { + toast.error("Something went wrong"); + console.error(e); + }); + } + + return ( + <form onSubmit={submitProposal}> + <label htmlFor="#payload">Payload</label> + <input + id="#payload" + type="text" + placeholder="(integer or hex, e.g.: 1 or 0x1)" + className="w-full p-2 mb-2 border rounded-lg border-slate-300" + onChange={(e) => setPayload(e.target.value)} + /> + <label htmlFor="#to_upgrade">To Upgrade</label> + <select + id="#to_upgrade" + className="w-full p-2 border rounded-lg border-slate-300" + onChange={(e) => setToUpgrade(e.target.value)} + > + {/* Carmine 0 = amm, 1 = governance, 2 = CARM token, 3 = merkle tree root, 4 = no-op/signal vote */} + <option value="0">amm</option> + <option value="1">governance</option> + <option value="2">CARM token</option> + <option value="3">merkle tree root</option> + <option value="4">no-op/signal vote</option> + </select> + + <button + type="submit" + className="w-full p-2 mt-4 text-white bg-blue-500 rounded-lg" + > + Submit + </button> + </form> + ); +} diff --git a/frontend/src/components/Proposal.tsx b/frontend/src/components/Proposal.tsx new file mode 100644 index 00000000..d40ffa29 --- /dev/null +++ b/frontend/src/components/Proposal.tsx @@ -0,0 +1,117 @@ +import { + useAccount, + useContractRead, + useContractWrite, +} from "@starknet-react/core"; +import { abi } from "../lib/abi"; +import React from "react"; +import { CONTRACT_ADDR } from "../lib/config"; +import toast from "react-hot-toast"; + +export default function Proposal({ + proposalId, + index, +}: { + proposalId: bigint; + index: number; +}) { + const { isConnected } = useAccount(); + + // Call the contract function get_proposal_details with the proposalId to get the proposal details + const { data, isLoading } = useContractRead({ + functionName: "get_proposal_details", + args: [proposalId.toString()], + abi, + address: CONTRACT_ADDR, + watch: true, + }); + + // Convert the proposal type from number to string + const proposal_type = { + 0: "amm", + 1: "governance", + 2: "CARM token", + 3: "merkle tree root", + 4: "no-op/signal vote", + }; + + const { writeAsync: write_yes } = useContractWrite({ + calls: [ + { + contractAddress: CONTRACT_ADDR, + entrypoint: "vote", + calldata: [proposalId.toString(), 1], + }, + ], + }); + + const { writeAsync: write_no } = useContractWrite({ + calls: [ + { + contractAddress: CONTRACT_ADDR, + entrypoint: "vote", + calldata: [proposalId.toString(), 2], + }, + ], + }); + + // Function to vote on a proposal + async function vote(vote: boolean) { + // Check if the user is connected to a wallet + if (!isConnected) { + // If the user is not connected, display a toast message + toast.error("Please connect your wallet to vote"); + return; + } + + // Call the write function to vote on the proposal + if (vote) { + // contract.invoke("vote", [proposalId.toString(), 1]); + + // await contract.functions.vote(proposalId.toString(), 1); + write_yes() + .then(() => { + toast.success("Voted Yes"); + }) + .catch((e) => { + toast.error("Something went wrong"); + console.error(e); + }); + } else { + write_no() + .then(() => { + toast.success("Voted No"); + }) + .catch((e) => { + toast.error("Something went wrong"); + console.error(e); + }); + } + } + + return isLoading ? ( + <div>loading contract {proposalId?.toString()}</div> + ) : ( + <div className="w-full max-w-[50rem] flex flex-row items-center gap-1 p-2 pl-0 rounded-lg bg-slate-200"> + <div className="self-stretch pl-5 pr-4 mr-4 font-mono border-r grid text-slate-400 place-content-center border-slate-400"> + {index} + </div> + <div>Type:</div> + <div className="flex-grow font-bold"> + {proposal_type[data.valueOf()["to_upgrade"]]} + </div> + <button + className="px-3 py-2 text-sm font-semibold bg-green-300 rounded-lg transition-all hover:bg-green-400" + onClick={() => vote(true)} + > + Vote Yes + </button> + <button + className="px-3 py-2 text-sm font-semibold bg-red-300 rounded-lg transition-all hover:bg-red-400" + onClick={() => vote(false)} + > + Vote No + </button> + </div> + ); +} diff --git a/frontend/src/components/starknet/ConnectModal.tsx b/frontend/src/components/starknet/ConnectModal.tsx new file mode 100644 index 00000000..9512d82e --- /dev/null +++ b/frontend/src/components/starknet/ConnectModal.tsx @@ -0,0 +1,34 @@ +"use client"; +import { Connector, useConnect } from "@starknet-react/core"; +import React from "react"; +import { Button } from "../ui/Button"; +import Dialog from "../ui/Dialog"; + +export default function ConnectModal() { + const { connect, connectors } = useConnect(); + + console.log(connectors); + return ( + <Dialog title="Connect Wallet"> + <div className="flex flex-col gap-2"> + {connectors.map((connector: Connector) => { + return ( + <Button + key={connector.id} + onClick={async () => + connector.available() ? connect({ connector }) : null + } + disabled={!connector.available()} + className="flex flex-row items-center justify-start gap-4 w-96" + > + {connector.icon.light && ( + <img src={connector.icon.dark} className="w-10 h-10" /> + )} + <p className="">Connect {connector.name}</p> + </Button> + ); + })} + </div> + </Dialog> + ); +} diff --git a/frontend/src/components/ui/Button.tsx b/frontend/src/components/ui/Button.tsx new file mode 100644 index 00000000..fc6af382 --- /dev/null +++ b/frontend/src/components/ui/Button.tsx @@ -0,0 +1,16 @@ +import React from "react"; + +interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { + children: React.ReactNode; +} + +export const Button = ({ children, ...props }: ButtonProps) => { + return ( + <button + {...props} + className={`px-3 py-2 bg-blue-500 rounded-md text-white disabled:opacity-50 ${props.className}`} + > + {children} + </button> + ); +}; diff --git a/frontend/src/components/ui/Dialog.tsx b/frontend/src/components/ui/Dialog.tsx new file mode 100644 index 00000000..d421c964 --- /dev/null +++ b/frontend/src/components/ui/Dialog.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import { Button } from "./Button"; + +export default function Dialog({ + children, + title, +}: { children: React.ReactNode; title: string }) { + const [isOpen, setIsOpen] = React.useState(false); + + return ( + <div> + <Button onClick={() => setIsOpen(true)}>{title}</Button> + {isOpen && ( + <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30"> + <div className="flex flex-col p-8 bg-white rounded-md gap-12"> + <div className="flex flex-row justify-between w-full"> + <h1 className="text-xl font-semibold">{title}</h1> + <button + type="button" + onClick={() => setIsOpen(false)} + className="px-4 py-2 font-medium text-white bg-gray-300 border border-transparent rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:text-sm" + > + x + </button> + </div> + {children} + </div> + </div> + )} + </div> + ); +} diff --git a/frontend/src/constants/amm.ts b/frontend/src/constants/amm.ts new file mode 100644 index 00000000..4e914184 --- /dev/null +++ b/frontend/src/constants/amm.ts @@ -0,0 +1,74 @@ +import config from "./config.json"; + +export const NETWORK = config.NETWORK as "mainnet" | "testnet"; +export const API_URL = config.API_URL; +export const AMM_ADDRESS = config.AMM_ADDRESS; +export const GOVERNANCE_ADDRESS = config.GOVERNANCE_ADDRESS; +export const ETH_ADDRESS = config.ETH_ADDRESS; +export const USDC_ADDRESS = config.USDC_ADDRESS; +export const BTC_ADDRESS = config.BTC_ADDRESS; +export const STRK_ADDRESS = config.STRK_ADDRESS; +export const ETH_USDC_CALL_ADDRESS = config.ETH_USDC_CALL_ADDRESS; +export const ETH_USDC_PUT_ADDRESS = config.ETH_USDC_PUT_ADDRESS; +export const BTC_USDC_CALL_ADDRESS = config.BTC_USDC_CALL_ADDRESS; +export const BTC_USDC_PUT_ADDRESS = config.BTC_USDC_PUT_ADDRESS; +export const ETH_STRK_CALL_ADDRESS = config.ETH_STRK_CALL_ADDRESS; +export const ETH_STRK_PUT_ADDRESS = config.ETH_STRK_PUT_ADDRESS; +export const STRK_USDC_CALL_ADDRESS = config.STRK_USDC_CALL_ADDRESS; +export const STRK_USDC_PUT_ADDRESS = config.STRK_USDC_PUT_ADDRESS; + +export const MAINNET_AUX_CONTRACT_ADDRESS = + "0x03e174d3d7dce00ad5e15299593a28c3defc660c77220867c921611a3aef4149"; + +export const LEGACY_AMM = + "0x076dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa"; +export const LEGACY_CALL_LP = + "0x7aba50fdb4e024c1ba63e2c60565d0fd32566ff4b18aa5818fc80c30e749024"; +export const LEGACY_PUT_LP = + "0x18a6abca394bd5f822cfa5f88783c01b13e593d1603e7b41b00d31d2ea4827a"; + +export const AMM_SWITCH_TIMESTAMP = 1704841200; + +export const isTestnet = NETWORK === "testnet"; +export const isMainnet = NETWORK === "mainnet"; +export const enum AMM_METHODS { + IS_OPTION_AVAILABLE = "is_option_available", + GET_POOL_AVAILABLE_BALANCE = "get_pool_available_balance", + APPROVE = "approve", + TRADE_OPEN = "trade_open", + TRADE_CLOSE = "trade_close", + TRADE_SETTLE = "trade_settle", + GET_AVAILABLE_OPTIONS = "get_available_options", + GET_OPTION_TOKEN_ADDRESS = "get_option_token_address", + GET_ALL_NON_EXPIRED_OPTIONS_WITH_PREMIA = "get_all_non_expired_options_with_premia", + GET_OPTION_WITH_POSITION_OF_USER = "get_option_with_position_of_user", + DEPOSIT_LIQUIDITY = "deposit_liquidity", + GET_USER_POOL_INFOS = "get_user_pool_infos", + WITHDRAW_LIQUIDITY = "withdraw_liquidity", + GET_TOTAL_PREMIA = "get_total_premia", + GET_MAX_LPOOL_BALANCE = "get_max_lpool_balance", + GET_LOOP_BALANCE = "get_lpool_balance", + GET_UNDERLYING_FOR_LPTOKENS = "get_underlying_for_lptokens", + GET_UNLOCKED_CAPITAL = "get_unlocked_capital", +} + +export const coreTeamAddresses = [ + "0x583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1", + "0x6717eaf502baac2b6b2c6ee3ac39b34a52e726a73905ed586e757158270a0af", + "0x11d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233", + "0x3d1525605db970fa1724693404f5f64cba8af82ec4aab514e6ebd3dec4838ad", + "0x3c032b19003bdd6f4155a30fffa0bda3a9cae45feb994a721299d7e5096568c", + // my Testnet wallet + "0x29af9cf62c9d871453f3b033e514dc790ce578e0e07241d6a5fedf19ceeaf08", +]; + +export const SLIPPAGE = 0.1; + +export const BASE_DIGITS = 18; +export const ETH_DIGITS = 18; +export const USDC_DIGITS = 6; +export const ETH_BASE_VALUE = BigInt(10) ** BigInt(ETH_DIGITS); +export const USDC_BASE_VALUE = BigInt(10) ** BigInt(USDC_DIGITS); +export const BASE_MATH_64_61 = BigInt(2) ** BigInt(61); +export const BASE_MATH_64 = BigInt(2) ** BigInt(64); +export const USDC_PRECISSION = 1000; diff --git a/frontend/src/constants/config.json b/frontend/src/constants/config.json new file mode 100644 index 00000000..e7f9b4d6 --- /dev/null +++ b/frontend/src/constants/config.json @@ -0,0 +1,18 @@ +{ + "NETWORK": "mainnet", + "API_URL": "https://api.carmine.finance", + "AMM_ADDRESS": "0x047472e6755afc57ada9550b6a3ac93129cc4b5f98f51c73e0644d129fd208d9", + "GOVERNANCE_ADDRESS": "0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f", + "ETH_ADDRESS": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "USDC_ADDRESS": "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + "BTC_ADDRESS": "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", + "STRK_ADDRESS": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "ETH_USDC_CALL_ADDRESS": "0x70cad6be2c3fc48c745e4a4b70ef578d9c79b46ffac4cd93ec7b61f951c7c5c", + "ETH_USDC_PUT_ADDRESS": "0x466e3a6731571cf5d74c5b0d9c508bfb71438de10f9a13269177b01d6f07159", + "BTC_USDC_CALL_ADDRESS": "0x35db72a814c9b30301f646a8fa8c192ff63a0dc82beb390a36e6e9eba55b6db", + "BTC_USDC_PUT_ADDRESS": "0x1bf27366077765c922f342c8de257591d1119ebbcbae7a6c4ff2f50ede4c54c", + "ETH_STRK_CALL_ADDRESS": "0x06df66db6a4b321869b3d1808fc702713b6cbb69541d583d4b38e7b1406c09aa", + "ETH_STRK_PUT_ADDRESS": "0x04dcd9632353ed56e47be78f66a55a04e2c1303ebcb8ec7ea4c53f4fdf3834ec", + "STRK_USDC_CALL_ADDRESS": "0x2b629088a1d30019ef18b893cebab236f84a365402fa0df2f51ec6a01506b1d", + "STRK_USDC_PUT_ADDRESS": "0x6ebf1d8bd43b9b4c5d90fb337c5c0647b406c6c0045da02e6675c43710a326f" +} diff --git a/frontend/src/globals.css b/frontend/src/globals.css new file mode 100644 index 00000000..4e9b1692 --- /dev/null +++ b/frontend/src/globals.css @@ -0,0 +1,20 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 255, 255, 255; + --background-end-rgb: 255, 255, 255; + } + + body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + transparent, + rgb(var(--background-end-rgb)) + ) + rgb(var(--background-start-rgb)); + } + \ No newline at end of file diff --git a/frontend/src/lib/abi.ts b/frontend/src/lib/abi.ts new file mode 100644 index 00000000..95955439 --- /dev/null +++ b/frontend/src/lib/abi.ts @@ -0,0 +1,411 @@ +export const abi = [ + { + name: "Governance", + type: "impl", + interface_name: "governance::contract::IGovernance", + }, + { + name: "governance::contract::IGovernance", + type: "interface", + items: [ + { + name: "get_governance_token_address", + type: "function", + inputs: [], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + { + name: "get_amm_address", + type: "function", + inputs: [], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + ], + }, + { + name: "Airdrop", + type: "impl", + interface_name: "governance::airdrop::IAirdrop", + }, + { + name: "governance::airdrop::IAirdrop", + type: "interface", + items: [ + { + name: "claim", + type: "function", + inputs: [ + { + name: "claimee", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "amount", + type: "core::integer::u128", + }, + { + name: "proof", + type: "core::array::Array::<core::felt252>", + }, + ], + outputs: [], + state_mutability: "external", + }, + ], + }, + { + name: "Proposals", + type: "impl", + interface_name: "governance::proposals::IProposals", + }, + { + name: "governance::types::PropDetails", + type: "struct", + members: [ + { + name: "payload", + type: "core::felt252", + }, + { + name: "to_upgrade", + type: "core::felt252", + }, + ], + }, + { + name: "governance::proposals::IProposals", + type: "interface", + items: [ + { + name: "vote", + type: "function", + inputs: [ + { + name: "prop_id", + type: "core::felt252", + }, + { + name: "opinion", + type: "core::felt252", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + name: "get_proposal_details", + type: "function", + inputs: [ + { + name: "prop_id", + type: "core::felt252", + }, + ], + outputs: [ + { + type: "governance::types::PropDetails", + }, + ], + state_mutability: "view", + }, + { + name: "get_vote_counts", + type: "function", + inputs: [ + { + name: "prop_id", + type: "core::felt252", + }, + ], + outputs: [ + { + type: "(core::integer::u128, core::integer::u128)", + }, + ], + state_mutability: "view", + }, + { + name: "submit_proposal", + type: "function", + inputs: [ + { + name: "payload", + type: "core::felt252", + }, + { + name: "to_upgrade", + type: "core::integer::u64", + }, + ], + outputs: [ + { + type: "core::felt252", + }, + ], + state_mutability: "external", + }, + { + name: "get_proposal_status", + type: "function", + inputs: [ + { + name: "prop_id", + type: "core::felt252", + }, + ], + outputs: [ + { + type: "core::felt252", + }, + ], + state_mutability: "view", + }, + { + name: "get_live_proposals", + type: "function", + inputs: [], + outputs: [ + { + type: "core::array::Array::<core::felt252>", + }, + ], + state_mutability: "view", + }, + { + name: "get_user_voted", + type: "function", + inputs: [ + { + name: "user_address", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "prop_id", + type: "core::felt252", + }, + ], + outputs: [ + { + type: "core::felt252", + }, + ], + state_mutability: "view", + }, + ], + }, + { + name: "constructor", + type: "constructor", + inputs: [ + { + name: "govtoken_address", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + }, + { + kind: "struct", + name: "governance::contract::Governance::Proposed", + type: "event", + members: [ + { + kind: "data", + name: "prop_id", + type: "core::felt252", + }, + { + kind: "data", + name: "payload", + type: "core::felt252", + }, + { + kind: "data", + name: "to_upgrade", + type: "core::integer::u64", + }, + ], + }, + { + kind: "struct", + name: "governance::contract::Governance::Voted", + type: "event", + members: [ + { + kind: "data", + name: "prop_id", + type: "core::felt252", + }, + { + kind: "data", + name: "voter", + type: "core::starknet::contract_address::ContractAddress", + }, + { + kind: "data", + name: "opinion", + type: "core::felt252", + }, + ], + }, + { + kind: "struct", + name: "governance::airdrop::airdrop::Claimed", + type: "event", + members: [ + { + kind: "data", + name: "address", + type: "core::starknet::contract_address::ContractAddress", + }, + { + kind: "data", + name: "received", + type: "core::integer::u128", + }, + ], + }, + { + kind: "enum", + name: "governance::airdrop::airdrop::Event", + type: "event", + variants: [ + { + kind: "nested", + name: "Claimed", + type: "governance::airdrop::airdrop::Claimed", + }, + ], + }, + { + kind: "struct", + name: "governance::proposals::proposals::Proposed", + type: "event", + members: [ + { + kind: "data", + name: "prop_id", + type: "core::felt252", + }, + { + kind: "data", + name: "payload", + type: "core::felt252", + }, + { + kind: "data", + name: "to_upgrade", + type: "core::integer::u64", + }, + ], + }, + { + kind: "struct", + name: "governance::proposals::proposals::Voted", + type: "event", + members: [ + { + kind: "data", + name: "prop_id", + type: "core::felt252", + }, + { + kind: "data", + name: "voter", + type: "core::starknet::contract_address::ContractAddress", + }, + { + kind: "data", + name: "opinion", + type: "core::felt252", + }, + ], + }, + { + kind: "enum", + name: "governance::proposals::proposals::Event", + type: "event", + variants: [ + { + kind: "nested", + name: "Proposed", + type: "governance::proposals::proposals::Proposed", + }, + { + kind: "nested", + name: "Voted", + type: "governance::proposals::proposals::Voted", + }, + ], + }, + { + kind: "struct", + name: "governance::upgrades::upgrades::Upgraded", + type: "event", + members: [ + { + kind: "data", + name: "prop_id", + type: "core::integer::u64", + }, + { + kind: "data", + name: "upgrade_type", + type: "core::integer::u64", + }, + ], + }, + { + kind: "enum", + name: "governance::upgrades::upgrades::Event", + type: "event", + variants: [ + { + kind: "nested", + name: "Upgraded", + type: "governance::upgrades::upgrades::Upgraded", + }, + ], + }, + { + kind: "enum", + name: "governance::contract::Governance::Event", + type: "event", + variants: [ + { + kind: "nested", + name: "Proposed", + type: "governance::contract::Governance::Proposed", + }, + { + kind: "nested", + name: "Voted", + type: "governance::contract::Governance::Voted", + }, + { + kind: "nested", + name: "AirdropEvent", + type: "governance::airdrop::airdrop::Event", + }, + { + kind: "nested", + name: "ProposalsEvent", + type: "governance::proposals::proposals::Event", + }, + { + kind: "nested", + name: "UpgradesEvent", + type: "governance::upgrades::upgrades::Event", + }, + ], + }, +]; diff --git a/frontend/src/lib/config.ts b/frontend/src/lib/config.ts new file mode 100644 index 00000000..6f9fa313 --- /dev/null +++ b/frontend/src/lib/config.ts @@ -0,0 +1,2 @@ +export const CONTRACT_ADDR = + "0x56dfcfa3c33c7a6852479f241f0cbbd2405791164754f16c0dcd90de13da059"; diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 00000000..3ae59b40 --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,63 @@ +import { mainnet } from "@starknet-react/chains"; +import { + StarknetConfig, + argent, + braavos, + // publicProvider, + useInjectedConnectors, + jsonRpcProvider, + // publicProvider, +} from "@starknet-react/core"; +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./globals.css"; +import { RpcProviderOptions } from "starknet"; +import { Toaster } from "react-hot-toast"; +// import { apiUrl } from "./api"; + +function Root({ children }: { children: React.ReactNode }) { + const chains = [mainnet]; + + // const SN_SEPOLIA_CHAINID = + // "0x534e5f5345504f4c4941" as constants.StarknetChainId; + + const testnetOptions: RpcProviderOptions = { + // nodeUrl: apiUrl("call", { network: "testnet" }), + nodeUrl: "https://free-rpc.nethermind.io/sepolia-juno", + // chainId: SN_SEPOLIA_CHAINID, + }; + + const provider = jsonRpcProvider({ + rpc: () => testnetOptions, + }); + // const provider = publicProvider(); + const { connectors } = useInjectedConnectors({ + // Show these connectors if the user has no connector installed. + recommended: [argent(), braavos()], + // Randomize the order of the connectors. + order: "random", + }); + + return ( + <StarknetConfig + autoConnect + chains={chains} + provider={provider} + connectors={connectors} + > + {children} + </StarknetConfig> + ); +} + +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( + // <React.StrictMode> + <Root> + <div> + <Toaster /> + </div> + <App /> + </Root> + // </React.StrictMode> +); diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// <reference types="vite/client" /> diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js new file mode 100644 index 00000000..90246381 --- /dev/null +++ b/frontend/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 00000000..6bd0ba2e --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + // "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json new file mode 100644 index 00000000..9d31e2ae --- /dev/null +++ b/frontend/tsconfig.node.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Node", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 00000000..40f81993 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,16 @@ +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; +import checker from "vite-plugin-checker"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + react(), + checker({ + typescript: true, + eslint: { + lintCommand: 'eslint "./src/**/*.{ts,tsx}"', + }, + }), + ], +}); From 0e0c0b7ca66c192ba47a25366cf256edf7576607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:54:21 +0200 Subject: [PATCH 16/39] Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0006b99c..437d6035 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,19 @@ Reach out to us via [Telegram](https://t.me/+_BpaFo4iarszZmQ0) We're rewarding contributors with fiat and STRK tokens through [OnlyDust](https://app.onlydust.com/p/carmine-options-amm). -## Setup +## Frontend + +A demo frontend accessing a deployment on Sepolia is available at http://34.171.48.97/ + +## Proposal notification service + +A Telegram bot sending notifications when a new proposal appears is operated by Carmine Finance for everyone, ping us on Telegram for access. + +### Available proposal types + +0. + +## Development setup Run this in a Devcontainer or on Codespaces in VSCode. Cairo, Scarb and the Cairo extension comes installed. From c51f55a90310120dfcc4911e905afb0c4c0bcd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:54:37 +0200 Subject: [PATCH 17/39] Update README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 437d6035..29d45968 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,6 @@ A demo frontend accessing a deployment on Sepolia is available at http://34.171. A Telegram bot sending notifications when a new proposal appears is operated by Carmine Finance for everyone, ping us on Telegram for access. -### Available proposal types - -0. - ## Development setup Run this in a Devcontainer or on Codespaces in VSCode. Cairo, Scarb and the Cairo extension comes installed. From 04f6801c45af44246639be0fe27b0b0013ed7b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hobza?= <hobza.tomas@gmail.com> Date: Fri, 3 May 2024 14:00:17 +0200 Subject: [PATCH 18/39] feat: default to_upgrade value (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomáš Hobza <xhobza03@vutbr.cz> --- frontend/src/components/NewProposalForm.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/NewProposalForm.tsx b/frontend/src/components/NewProposalForm.tsx index 7e3e797d..b9fdec66 100644 --- a/frontend/src/components/NewProposalForm.tsx +++ b/frontend/src/components/NewProposalForm.tsx @@ -12,7 +12,7 @@ export default function NewProposalForm({ // State variables for the payload and to_upgrade const [payload, setPayload] = React.useState<string>(""); - const [to_upgrade, setToUpgrade] = React.useState<string>(""); + const [to_upgrade, setToUpgrade] = React.useState<string>("0"); // Create a call to submit a proposal const calls = useMemo(() => { @@ -46,11 +46,13 @@ export default function NewProposalForm({ writeAsync() .then(() => { toast.success("Proposal submitted"); - setIsModalOpen(false); }) .catch((e) => { toast.error("Something went wrong"); console.error(e); + }) + .finally(() => { + setIsModalOpen(false); }); } @@ -69,6 +71,7 @@ export default function NewProposalForm({ id="#to_upgrade" className="w-full p-2 border rounded-lg border-slate-300" onChange={(e) => setToUpgrade(e.target.value)} + defaultValue={to_upgrade} > {/* Carmine 0 = amm, 1 = governance, 2 = CARM token, 3 = merkle tree root, 4 = no-op/signal vote */} <option value="0">amm</option> From 9f144275b361e6e26271227ee9b884bafa82eb8b Mon Sep 17 00:00:00 2001 From: xkrivan5 <116671001+xkrivan5@users.noreply.github.com> Date: Sat, 4 May 2024 15:57:34 +0200 Subject: [PATCH 19/39] Telegram Notification bot for proposal (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * initial commit * change to testnet * Add basic working event printing * notification telegram bot working * add gitignore * Remove node_modules folder and update .gitignore * update config.toml * removing unused address * Delete accidentally committed tests/proposal.cairo * code review changes * rest of the code-review changes * Update packages according to code review feedback * Add error print when unable to send messages to Telegram * Add automatic retrieval of chain id * Polish formatting * Refactor config file reading * code-review changes in index.ts, package-lock * Add CI runner * Trigger CI * Fix CI * Fix CI * Fix CI * Fix CI --------- Co-authored-by: Ondřej Sojka <ondrej.sojka@gmail.com> Co-authored-by: Ondřej Sojka <8470346+tensojka@users.noreply.github.com> --- .github/workflows/tsc.yml | 28 + .gitignore | 21 +- notification-bot/config.toml | 15 + notification-bot/package-lock.json | 2228 ++++++++++++++++++++++++++++ notification-bot/package.json | 31 + notification-bot/src/index.ts | 230 +++ notification-bot/tsconfig.json | 11 + 7 files changed, 2563 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/tsc.yml create mode 100644 notification-bot/config.toml create mode 100644 notification-bot/package-lock.json create mode 100644 notification-bot/package.json create mode 100644 notification-bot/src/index.ts create mode 100644 notification-bot/tsconfig.json diff --git a/.github/workflows/tsc.yml b/.github/workflows/tsc.yml new file mode 100644 index 00000000..0205c620 --- /dev/null +++ b/.github/workflows/tsc.yml @@ -0,0 +1,28 @@ +name: Typescript + +on: + push: + paths: + - '**.ts' + - '.github/' + - 'tsconfig.json' + - 'package.json' + pull_request: + paths: + - '**.ts' + - '.github/' + - 'tsconfig.json' + - 'package.json' + +jobs: + compile: + runs-on: ubuntu-latest + steps: + - name: Checkout (GitHub) + uses: actions/checkout@v4 + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + - name: Run tsc + run: cd notification-bot; npm install --save-dev; tsc --project . \ No newline at end of file diff --git a/.gitignore b/.gitignore index 98cbdd5d..4b5e8a02 100644 --- a/.gitignore +++ b/.gitignore @@ -9,10 +9,29 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk +# IDE settings .vscode + +# Environment variables .env +# Dependency directories vendor/ + +# Node.js modules +node_modules/ +*.js + +# OS files .DS_Store + +# Foundry related .snfoundry_cache/ -account* \ No newline at end of file + +# Account-related files that might start with 'account' +account* + +# TypeScript files to be ignored +*.tsbuildinfo # TypeScript build information files +dist/ # Common directory for compiled JavaScript files +build/ # Alternative directory for compiled files \ No newline at end of file diff --git a/notification-bot/config.toml b/notification-bot/config.toml new file mode 100644 index 00000000..895ad6b3 --- /dev/null +++ b/notification-bot/config.toml @@ -0,0 +1,15 @@ +[telegram] +bot_api_key = "" +chat_id = "" + +[apibara] +url = "" +token = "" + +[starknet] +nodeUrl = "" +chain = "sepolia" + +[governance] +gov_contract_address = "" +event_selector = "0x01b5f21c50bf3288fb310446824298a349f0ed9e28fb480cc9a4d54d034652e1" # ProposalSubmit diff --git a/notification-bot/package-lock.json b/notification-bot/package-lock.json new file mode 100644 index 00000000..0c5469e8 --- /dev/null +++ b/notification-bot/package-lock.json @@ -0,0 +1,2228 @@ +{ + "name": "apibara-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "apibara-server", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@apibara/protocol": "^0.4.9", + "@apibara/starknet": "^0.5.0", + "body-parser": "^1.20.2", + "dotenv": "^16.4.5", + "ethers": "^6.12.0", + "fs": "^0.0.1-security", + "logger": "^0.0.1", + "starknet": "^6.7.0", + "toml": "^3.0.0" + }, + "devDependencies": { + "@types/body-parser": "^1.19.5", + "@types/express": "^4.17.21", + "@types/logger": "^0.0.5", + "nodemon": "^3.1.0", + "ts-node": "^10.9.2", + "typescript": "^5.4.5" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, + "node_modules/@apibara/protocol": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@apibara/protocol/-/protocol-0.4.9.tgz", + "integrity": "sha512-RTpZ9u8zmDHbgMYDO47lnJlGxUrfCjKUGZ10SmicoN7OkNyAWmVGrwXZYfQJMw81bSObet7vU76iQ1HznyiySA==", + "dependencies": { + "@grpc/grpc-js": "^1.7.3", + "@grpc/proto-loader": "^0.7.3", + "google-protobuf": "^3.21.2", + "long": "^5.2.1", + "protobufjs": "^7.1.2" + } + }, + "node_modules/@apibara/starknet": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@apibara/starknet/-/starknet-0.5.0.tgz", + "integrity": "sha512-xzpXMlwdDeBb7IpY9CYKs7uBDz1uz9gb8rR3QgWVx7xipB/fQY6InHldyX5zfLIuBVblZOlenviNrBXOd7Wlsw==", + "dependencies": { + "google-protobuf": "^3.21.2", + "long": "^5.2.1", + "protobufjs": "^7.1.2" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.6.tgz", + "integrity": "sha512-xP58G7wDQ4TCmN/cMUHh00DS7SRDv/+lC+xFLrTkMIN8h55X5NhZMLYbvy7dSELP15qlI6hPhNCRWVMtZMwqLA==", + "dependencies": { + "@grpc/proto-loader": "^0.7.10", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.12", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.12.tgz", + "integrity": "sha512-DCVwMxqYzpUCiDMl7hQ384FqP4T3DbNpXU8pt681l3UWCip1WUiD5JrkImUwCB9a7f2cq4CUTmi5r/xIMRPY1Q==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@scure/base": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/starknet": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@scure/starknet/-/starknet-1.0.0.tgz", + "integrity": "sha512-o5J57zY0f+2IL/mq8+AYJJ4Xpc1fOtDhr+mFQKbHnYFmm3WQrC+8zj2HEgxak1a+x86mhmBC1Kq305KUpVf0wg==", + "dependencies": { + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/starknet/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/starknet/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz", + "integrity": "sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/logger": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@types/logger/-/logger-0.0.5.tgz", + "integrity": "sha512-oIqUeHrT4HrFtV1pRDltA32XDdOcd6IQLfaZcBfsDuB0ncrKEp0klXFSPL+KVnReEtScb6awxMpHg6RiBKiRcw==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/abi-wan-kanabi": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/abi-wan-kanabi/-/abi-wan-kanabi-2.2.2.tgz", + "integrity": "sha512-sTCv2HyNIj1x2WFUoc9oL8ZT9liosrL+GoqEGZJK1kDND096CfA7lwx06vLxLWMocQ41FQXO3oliwoh/UZHYdQ==", + "dependencies": { + "ansicolors": "^0.3.2", + "cardinal": "^2.1.1", + "fs-extra": "^10.0.0", + "yargs": "^17.7.2" + }, + "bin": { + "generate": "dist/generate.js" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ethers": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.12.0.tgz", + "integrity": "sha512-zL5NlOTjML239gIvtVJuaSk0N9GQLi1Hom3ZWUszE5lDTQE/IVB62mrPkQ2W1bGcZwVGSLaetQbWNQSvI4rGDQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "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.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/fetch-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-3.0.1.tgz", + "integrity": "sha512-ZGXe8Y5Z/1FWqQ9q/CrJhkUD73DyBU9VF0hBQmEO/wPHe4A9PKTjplFDLeFX8aOsYypZUcX5Ji/eByn3VCVO3Q==", + "dependencies": { + "set-cookie-parser": "^2.4.8", + "tough-cookie": "^4.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/logger": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/logger/-/logger-0.0.1.tgz", + "integrity": "sha512-UD45f4iZrsj6dQKt5QBN7K+R0hmFwGS8G+Pv8WtHjrnhrMQftIclma8b86mNtg1LKB6HDIOW/ZtjnXELBhr89w==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/lossless-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.0.1.tgz", + "integrity": "sha512-l0L+ppmgPDnb+JGxNLndPtJZGNf6+ZmVaQzoxQm3u6TXmhdnsA+YtdVR8DjzZd/em58686CQhOFDPewfJ4l7MA==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nodemon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", + "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "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": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/starknet": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/starknet/-/starknet-6.7.0.tgz", + "integrity": "sha512-8NMedKBfkg/oZUgTYNw9lKeNoNYakL/Roah2HwKzrVyvDxBs0arrNrR8No8+tTq0wQg0HGu1w+JIObynjHAK3w==", + "dependencies": { + "@noble/curves": "~1.4.0", + "@scure/base": "~1.1.3", + "@scure/starknet": "~1.0.0", + "abi-wan-kanabi": "^2.2.2", + "fetch-cookie": "^3.0.0", + "isomorphic-fetch": "^3.0.0", + "lossless-json": "^4.0.1", + "pako": "^2.0.4", + "starknet-types": "^0.0.4", + "ts-mixer": "^6.0.3", + "url-join": "^4.0.1" + } + }, + "node_modules/starknet-types": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/starknet-types/-/starknet-types-0.0.4.tgz", + "integrity": "sha512-PklqFeSp9gMqbzW5IbO8l1s3xsNZYkNG/x/gsytgYCIl6H/cqiwCZolVTneyTibvrdHOQ8kP3PXwfdsypudYqw==" + }, + "node_modules/starknet/node_modules/@noble/curves": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", + "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/starknet/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-mixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + } + } +} diff --git a/notification-bot/package.json b/notification-bot/package.json new file mode 100644 index 00000000..67f92f8a --- /dev/null +++ b/notification-bot/package.json @@ -0,0 +1,31 @@ +{ + "name": "apibara-server", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "nodemon --exec ts-node src/index.ts" + }, + "keywords": [], + "author": "", + "license": "Apache-2.0", + "dependencies": { + "@apibara/protocol": "^0.4.9", + "@apibara/starknet": "^0.5.0", + "body-parser": "^1.20.2", + "dotenv": "^16.4.5", + "ethers": "^6.12.0", + "fs": "^0.0.1-security", + "logger": "^0.0.1", + "starknet": "^6.7.0", + "toml": "^3.0.0" + }, + "devDependencies": { + "@types/body-parser": "^1.19.5", + "@types/express": "^4.17.21", + "@types/logger": "^0.0.5", + "nodemon": "^3.1.0", + "ts-node": "^10.9.2", + "typescript": "^5.4.5" + } +} diff --git a/notification-bot/src/index.ts b/notification-bot/src/index.ts new file mode 100644 index 00000000..9f22918e --- /dev/null +++ b/notification-bot/src/index.ts @@ -0,0 +1,230 @@ +import { StreamClient } from "@apibara/protocol"; +import { + Filter, + StarkNetCursor, + v1alpha2, + FieldElement, + EventFilter, +} from "@apibara/starknet"; + +import { RpcProvider, constants } from "starknet"; +import * as dotenv from "dotenv"; +import * as fs from "fs"; +import * as toml from "toml"; + +function getConfig() { + dotenv.config(); + + const configPath = process.env.CONFIG_PATH || 'config.toml'; + const config = toml.parse(fs.readFileSync(configPath, 'utf-8')); + + const BOT_API_KEY = config.telegram?.bot_api_key; + const CHAT_ID = config.telegram?.chat_id; + const CLIENT_URL = config.apibara?.url; + const CLIENT_TOKEN = config.apibara?.token; + const GOV_CONTRACT_ADDRESS = config.governance?.gov_contract_address; + const configured_chain_name = config.starknet?.chain as ChainName; + if (!BOT_API_KEY || !CHAT_ID || !CLIENT_URL || !CLIENT_TOKEN || !GOV_CONTRACT_ADDRESS || !configured_chain_name) { + alert('required fields in configuration file not found') + console.error('required fields in configuration file not found'); process.exit(1) + } + + + const SUPPORTED_CHAINS = { + 'sepolia': (constants.StarknetChainId.SN_SEPOLIA, constants.NetworkName.SN_SEPOLIA), + 'mainnet': (constants.StarknetChainId.SN_MAIN, constants.NetworkName.SN_MAIN) + }; + type ChainName = keyof typeof SUPPORTED_CHAINS; + if (!SUPPORTED_CHAINS[configured_chain_name]) { + throw new Error('Invalid chain name in configuration file'); + } + const CHAIN_ID = SUPPORTED_CHAINS[configured_chain_name][0]; + const NODE_URL = config.starknet?.nodeUrl ?? SUPPORTED_CHAINS[configured_chain_name][1]; + + const PROPOSED_EVENT_SELECTOR = config.governance!.event_selector ?? "0x01b5f21c50bf3288fb310446824298a349f0ed9e28fb480cc9a4d54d034652e1"; + + + const result = { + 'BOT_API_KEY': BOT_API_KEY, + 'CHAT_ID': CHAT_ID, + 'CLIENT_URL': CLIENT_URL, + 'CLIENT_TOKEN': CLIENT_TOKEN, + 'GOV_CONTRACT_ADDRESS': GOV_CONTRACT_ADDRESS, + 'NODE_URL': NODE_URL, + 'CHAIN_ID': CHAIN_ID as constants.StarknetChainId, // typescript could be smarter... :/ + 'PROPOSED_EVENT_SELECTOR': PROPOSED_EVENT_SELECTOR + } + + return result; +} + +const conf = getConfig(); + + +/** + * Initializes the StreamClient with configuration loaded from environment variables. + * @returns {StreamClient} Configured StreamClient instance for connecting to Apibara. + */ +function initializeStreamClient() { + return new StreamClient({ + url: conf.CLIENT_URL, + token: conf.CLIENT_TOKEN, + async onReconnect(err, retryCount) { + console.log("reconnect", err, retryCount); + await new Promise((resolve) => setTimeout(resolve, 1000)); + return { reconnect: true }; + }, + }); +} + +/** + * Initializes the event filter configuration for the Apibara client. + * @returns {string} Encoded filter string used to specify which blockchain events to listen to. + */ +function initializeFilter() { + const governance_contract_address = FieldElement.fromBigInt(conf.GOV_CONTRACT_ADDRESS); + return Filter.create() + .withHeader({ weak: true }) + .addEvent(new EventFilter().withFromAddress(governance_contract_address)) + .encode(); +} + +/** + * Configures the Apibara client with a specific filter and block number. + * @param {StreamClient} client The Apibara client instance to configure. + * @param {string} filter The encoded filter specifying the events to listen for. + * @param {number} block_number The blockchain block number from which to start listening. + */ +function configureClient(client: StreamClient, filter: Uint8Array, block_number: number) { + client.configure({ + filter: filter, + batchSize: 1, + cursor: StarkNetCursor.createWithBlockNumber(block_number), + }); +} + +/** + * Main entry point for the event monitoring script. + * Initializes the StreamClient and RpcProvider for connecting to the StarkNet blockchain. + * Configures the Apibara client to listen for specific blockchain events and processes them accordingly. + */ +async function main() { + try { + // Apibara streaming + const client = initializeStreamClient(); + + const provider = new RpcProvider({ + nodeUrl: conf.NODE_URL, + chainId: conf.CHAIN_ID, + }); + + const hashAndBlockNumber = await provider.getBlockLatestAccepted(); + const block_number = hashAndBlockNumber.block_number; + + const filter_test = initializeFilter(); + + // Configure the apibara client + configureClient(client, filter_test, block_number); + await listenToMessages(client); + + } catch (error) { + console.error("Initialization failed", error); + process.exit(1); + } +} + +/** + * Listens to blockchain events and handles each submit proposal event as they are received. + * @param {StreamClient} client The Apibara client instance from which to listen for messages. + */ +async function listenToMessages(client: StreamClient) { + for await (const message of client) { + if (message.message === "data" && message.data?.data) { + for (const data of message.data.data) { + const block = v1alpha2.Block.decode(data); + + const { header, events, transactions } = block; + + if (!header || !transactions) { + continue; + } + + for (const event of events) { + if (event.event && event.event.keys && event.event.data) { + for (let evtkey of event.event!.keys) { + let evtkey_hex = FieldElement.toHex(evtkey); + if (evtkey_hex === conf.PROPOSED_EVENT_SELECTOR) { + handleEventSubmitProposal(event.event); + } + } + } + } + } + } + } +} + + +main() + .then(() => process.exit(0)) + .catch((error) => { + alert(error.message); + process.exit(1); + }); + +/** + * Handles individual blockchain events, and notifies user for proposal submission events. + * @param {v1alpha2.IBlockHeader} header The header of the blockchain block containing the event. + * @param {v1alpha2.IEvent} event The event to process. + */ +async function handleEventSubmitProposal( + event: v1alpha2.IEvent, +) { + console.log("STARTING TO HANDLE PROPOSAL"); + const sender = event.fromAddress ? FieldElement.toHex(event.fromAddress) : null; + + if (!Array.isArray(event.data) || event.data.length < 3) { + const message = `No sufficient data found in event from Sender: ${sender}`; + console.log(message); + alert(message); + return; + } + + const payload = FieldElement.toHex(event.data[1]); + const to_upgrade = FieldElement.toBigInt(event.data[2]).toString(); + const prop_id = FieldElement.toBigInt(event.data[0]).toString(); + + if (sender && payload && to_upgrade) { + const message = `New proposal: + - Sender: ${sender} + - Payload: ${payload} + - Proposal ID: ${prop_id} + - To upgrade: ${to_upgrade}`; + console.log(message); + alert(message); + } else { + + alert('aborting proposal handling due to missing data in event'); + + } +} + +/** + * Sends a notification message via Telegram API. + * @param {string} msg The message to send. + */ +async function alert(msg: string): Promise<void> { + + const url = new URL(`https://api.telegram.org/bot${conf.BOT_API_KEY}/sendMessage`); + url.searchParams.append('chat_id', conf.CHAT_ID); + url.searchParams.append('text', msg); + + try { + const response = await fetch(url.toString()); + const text = await response.text(); + response.ok ? console.log("Notification sent to Telegram") : console.error(`Failed to send notifications to Telegram.Status ${response.status}, response ${text}`); + } catch (e) { + console.error("Failed to send notifications to Telegram", e); + } +} + diff --git a/notification-bot/tsconfig.json b/notification-bot/tsconfig.json new file mode 100644 index 00000000..409e1274 --- /dev/null +++ b/notification-bot/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + "target": "esnext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "module": "commonjs", /* Specify what module code is generated. */ + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, /* Enable all strict type-checking options. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} \ No newline at end of file From b144b857c0a8b3e5a3d7df5ce5ee3af00e9690a6 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Mon, 13 May 2024 20:06:38 +0000 Subject: [PATCH 20/39] Adding proposals tests --- tests/proposals_tests.cairo | 85 +++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/proposals_tests.cairo diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo new file mode 100644 index 00000000..63bf4d68 --- /dev/null +++ b/tests/proposals_tests.cairo @@ -0,0 +1,85 @@ +use array::ArrayTrait; +use core::traits::TryInto; +use debug::PrintTrait; +use starknet::ContractAddress; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use snforge_std::{ + BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget +}; + +mod setup; +use setup::{ + deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy +}; +use governance::contract::IGovernanceDispatcher; +use governance::contract::IGovernanceDispatcherTrait; +use governance::proposals::IProposalsDispatcher; +use governance::proposals::IProposalsDispatcherTrait; +use governance::upgrades::IUpgradesDispatcher; +use governance::upgrades::IUpgradesDispatcherTrait; +use governance::constants; +use starknet::get_block_timestamp; + + +const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; + +const first_address: ContractAddress = 0x1.try_into().unwrap(); +const second_address: ContractAddress = 0x2.try_into().unwrap(); +const admin_addr: ContractAddress = 0x3.try_into().unwrap(); + + +fn test_express_proposal() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + dispatcher.vote(prop_id, 1); + + assert(dispatcher.get_proposal_status(prop_id) == 1, "proposal not passed!"); +} + +#[should_panic] +fn test_proposal_expiry() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + //simulate passage of time + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + start_warp(end_timestamp + 1, gov_contract_addr.into()); + + let status = dispatcher.get_proposal_status(prop_id); +} + +#[should_panic] +fn test_vote_on_expired_proposal() { + let gov_contract = deploy_governance(); + let gov_contract_addr = gov_contract.contract_address; + let token_contract = deploy_and_distribute_gov_tokens(admin_addr); + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + let prop_id = dispatcher.submit_proposal(42, 1); + + //simulate passage of time + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + start_warp(end_timestamp + 1, gov_contract_addr.into()); + + start_prank(CheatTarget::One(gov_contract_addr), first_address); + dispatcher.vote(prop_id, 1); +} + From d4fdf9b7097ea3cab8320d26dbd6b1505e5df6b3 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Mon, 13 May 2024 20:23:07 +0000 Subject: [PATCH 21/39] Comment code for airdrop_tests and remove old setup file --- src/airdrop.cairo | 2 +- tests/airdrop_tests.cairo | 185 ++++++++++++++++++-------------------- tests/setup.cairo | 175 ------------------------------------ 3 files changed, 86 insertions(+), 276 deletions(-) delete mode 100644 tests/setup.cairo diff --git a/src/airdrop.cairo b/src/airdrop.cairo index 0332d27e..b9a934ff 100644 --- a/src/airdrop.cairo +++ b/src/airdrop.cairo @@ -28,7 +28,7 @@ mod airdrop { use governance::contract::Governance::ContractState; use governance::traits::IGovernanceTokenDispatcher; use governance::traits::IGovernanceTokenDispatcherTrait; - + #[storage] struct Storage { airdrop_claimed: LegacyMap::<ContractAddress, u128>, diff --git a/tests/airdrop_tests.cairo b/tests/airdrop_tests.cairo index 4eae2700..b5874641 100644 --- a/tests/airdrop_tests.cairo +++ b/tests/airdrop_tests.cairo @@ -1,100 +1,85 @@ -use core::hash::HashStateExTrait; -use core::{ArrayTrait, SpanTrait}; -use core::debug::PrintTrait; -use governance::airdrop::{airdrop, IAirdropDispatcher, IAirdropDispatcherTrait}; -use airdrop::STRK_ADDRESS; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use snforge_std::{ContractClassTrait, declare, start_prank, CheatTarget}; -use starknet::{ContractAddress, deploy_syscall}; - -const ADMIN_ADDR: felt252 = 0x42; -const CLAIMEE_1: felt252 = 0x13; -const CLAIMEE_2: felt252 = 0x14; - - -fn deploy() -> IAirdropDispatcher { - let mut calldata = ArrayTrait::new(); - calldata.append(ADMIN_ADDR); - - let contract = declare('Airdrop'); - let address = contract.deploy().expect('unable to deploy Airdrop'); - IAirdropDispatcher { contract_address: address } -} - - -fn deploy_token(recipient: ContractAddress) -> IERC20Dispatcher { - let mut calldata = ArrayTrait::new(); - calldata.append(1000000000000000000); - calldata.append(0); - calldata.append(recipient.into()); - let contract = declare('MyToken'); - let address = contract - .deploy_at(@calldata, STRK_ADDRESS.try_into().unwrap()) - .expect('unable to deploy mockstrk'); - - IERC20Dispatcher { contract_address: address } -} - -#[test] -fn test_claim_twice_with_same_proof() { - let airdrop_contract = deploy(); - let token_contract = deploy_token(airdrop_contract.contract_address); - - start_prank(CheatTarget::One(airdrop_contract.contract_address), ADMIN_ADDR.try_into().unwrap()); - airdrop_contract.add_root(valid_root); - - start_prank(CheatTarget::One(airdrop_contract.contract_address), CLAIMEE_1.try_into().unwrap()); - let initial_proof = array![valid_proof_element]; - airdrop_contract.claim(CLAIMEE_1, valid_claim_amount, initial_proof.span()); - assert(token_contract.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "First claim failed"); - - airdrop_contract.claim(CLAIMEE_1, valid_claim_amount, initial_proof.span()); - assert(token_contract.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, "Second claim modified the claimee's balance"); -} - - -#[test] -#[should_panic(expected: ('INVALID PROOF',))] -fn test_claim_invalid_proof() { - let contract = deploy(); - deploy_token(contract.contract_address); - start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); - contract.add_root(0xf7c8d3f309262572ad35df8ff6c33f24d8114c60eac3bc27bf42382ca82faf); - - start_prank( - CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap() - ); - let proof = array![ - 0x2a18afb0550a011d54ca3940648e59894c06e4c3d0a611256c0b575bd528b3b, - 0x1 - ]; - contract.claim(0x88, proof.span()); -} - -#[test] -fn test_update_root_and_claim_attempts() { - let contract = deploy(); - let tok = deploy_token(contract.contract_address); - start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); - - // add intial root and valid claim - contract.add_root(initial_root); - start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap()); - contract.claim(claim_amount, valid_proof_for_initial_root.span()); - assert(tok.balance_of(CLAIMEE_1.try_into().unwrap()) == claim_amount, 'initial claim failed'); - - // update root - start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); - contract.add_root(new_root); - - // claim with old root + new proof, should fail - start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_2.try_into().unwrap()); - contract.claim(claim_amount, new_proof_not_matching_old_root.span()); - // check fail : to do, use should panic ? - - // claim with new root + old proof, should fail - contract.claim(claim_amount, old_proof_not_matching_new_root.span()); - // check fail : to do -} - - +// use core::hash::HashStateExTrait; +// use core::{ArrayTrait, SpanTrait}; +// use core::debug::PrintTrait; +// use governance::airdrop::{airdrop, IAirdropDispatcher, IAirdropDispatcherTrait}; +// use airdrop::STRK_ADDRESS; +// use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +// use snforge_std::{ContractClassTrait, declare, start_prank, CheatTarget}; +// use starknet::{ContractAddress, deploy_syscall}; + +// const ADMIN_ADDR: felt252 = 0x42; +// const CLAIMEE_1: felt252 = 0x13; +// const CLAIMEE_2: felt252 = 0x14; + +// fn deploy() -> IAirdropDispatcher { +// let mut calldata = ArrayTrait::new(); +// calldata.append(ADMIN_ADDR); + +// let contract = declare('Airdrop'); +// let address = contract.deploy().expect('unable to deploy Airdrop'); +// IAirdropDispatcher { contract_address: address } +// } + +// #[test] +// fn test_claim_twice_with_same_proof() { +// let airdrop_contract = deploy(); +// let token_contract = deploy_token(airdrop_contract.contract_address); + +// start_prank( +// CheatTarget::One(airdrop_contract.contract_address), ADMIN_ADDR.try_into().unwrap() +// ); +// airdrop_contract.add_root(valid_root); + +// start_prank(CheatTarget::One(airdrop_contract.contract_address), CLAIMEE_1.try_into().unwrap()); +// let initial_proof = array![valid_proof_element]; +// airdrop_contract.claim(CLAIMEE_1, valid_claim_amount, initial_proof.span()); +// assert( +// token_contract.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, +// "First claim failed" +// ); + +// airdrop_contract.claim(CLAIMEE_1, valid_claim_amount, initial_proof.span()); +// assert( +// token_contract.balance_of(CLAIMEE_1.try_into().unwrap()) == valid_claim_amount, +// "Second claim modified the claimee's balance" +// ); +// } + +// #[test] +// #[should_panic(expected: ('INVALID PROOF',))] +// fn test_claim_invalid_proof() { +// let contract = deploy(); +// deploy_token(contract.contract_address); +// start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); +// contract.add_root(0xf7c8d3f309262572ad35df8ff6c33f24d8114c60eac3bc27bf42382ca82faf); + +// start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap()); +// let proof = array![0x2a18afb0550a011d54ca3940648e59894c06e4c3d0a611256c0b575bd528b3b, 0x1]; +// contract.claim(0x88, proof.span()); +// } + +// #[test] +// fn test_update_root_and_claim_attempts() { +// let contract = deploy(); +// let tok = deploy_token(contract.contract_address); +// start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); + +// // add intial root and valid claim +// contract.add_root(initial_root); +// start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_1.try_into().unwrap()); +// contract.claim(claim_amount, valid_proof_for_initial_root.span()); +// assert(tok.balance_of(CLAIMEE_1.try_into().unwrap()) == claim_amount, 'initial claim failed'); + +// // update root +// start_prank(CheatTarget::One(contract.contract_address), ADMIN_ADDR.try_into().unwrap()); +// contract.add_root(new_root); + +// // claim with old root + new proof, should fail +// start_prank(CheatTarget::One(contract.contract_address), CLAIMEE_2.try_into().unwrap()); +// contract.claim(claim_amount, new_proof_not_matching_old_root.span()); +// // check fail : to do, use should panic ? + +// // claim with new root + old proof, should fail +// contract.claim(claim_amount, old_proof_not_matching_new_root.span()); +// // check fail : to do +// } diff --git a/tests/setup.cairo b/tests/setup.cairo deleted file mode 100644 index 7d240631..00000000 --- a/tests/setup.cairo +++ /dev/null @@ -1,175 +0,0 @@ -use core::traits::Into; -#[starknet::contract] -mod MyToken { - use openzeppelin::token::erc20::ERC20Component; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>; - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>; - impl InternalImpl = ERC20Component::InternalImpl<ContractState>; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, fixed_supply: u256, recipient: ContractAddress) { - let name = 'MyToken'; - let symbol = 'MTK'; - - self.erc20.initializer(name, symbol); - self.erc20._mint(recipient, fixed_supply); - } -} - -use array::ArrayTrait; -use core::traits::TryInto; -use debug::PrintTrait; -use starknet::ContractAddress; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use snforge_std::{ - BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget -}; - -use governance::contract::IGovernanceDispatcher; -use governance::contract::IGovernanceDispatcherTrait; -use governance::proposals::IProposalsDispatcher; -use governance::proposals::IProposalsDispatcherTrait; -use governance::upgrades::IUpgradesDispatcher; -use governance::upgrades::IUpgradesDispatcherTrait; -use governance::constants; -use starknet::get_block_timestamp; - - -const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; - -const first_address: ContractAddress = 0x1.try_into().unwrap(); -const second_address: ContractAddress = 0x2.try_into().unwrap(); -const admin_addr: ContractAddress = 0x3.try_into().unwrap(); - -fn deploy_governance() -> IGovernanceDispatcher { - let gov_contract = declare('Governance'); - let address = gov_contract.deploy().expect('unable to deploy governance'); - IGovernanceDispatcher { contract_address: address }; -} - - -fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) { - let mut calldata = ArrayTrait::new(); - calldata.append(GOV_TOKEN_INITIAL_SUPPLY); - calldata.append(recipient.into()); - - let gov_token_contract = declare('MyToken'); - let token_addr = gov_token_contract.deploy_at(@calldata).expect('unable to deploy MyToken'); - let token: IERC20Dispatcher = IERC20Dispatcher { contract_address: token_addr }; - - start_prank(CheatTarget::One(token_addr), admin_addr); - - token.transfer(first_address, 100000); - token.transfer(second_address, 100000); -} - - -fn test_vote_upgrade_root(new_merkle_root: felt252) { - let gov_contract = deploy_governance(); - let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); - - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - let prop_id = dispatcher.submit_proposal(new_merkle_root, 3); - - start_prank(CheatTarget::One(gov_contract_addr), first_address); - dispatcher.vote(prop_id, 1); - start_prank(CheatTarget::One(gov_contract_addr), second_address); - dispatcher.vote(prop_id, 1); - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - dispatcher.vote(prop_id, 1); - - assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); - - let upgrade_dispatcher = IUpgradesDispatcher { contract_address: gov_contract_addr }; - upgrade_dispatcher.apply_passed_proposal(prop_id); - assert(check_if_healthy(gov_contract_addr), 'new gov not healthy'); -} - -fn check_if_healthy(gov_contract_addr: ContractAddress) -> bool { - // TODO - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - dispatcher.get_proposal_status(0); - let prop_details = dispatcher.get_proposal_details(0); - (prop_details.payload + prop_details.to_upgrade) != 0 -} - - -fn test_express_proposal() { - let gov_contract = deploy_governance(); - let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); - - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - let prop_id = dispatcher.submit_proposal(42, 1); - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - dispatcher.vote(prop_id, 1); - - assert(dispatcher.get_proposal_status(prop_id) == 1, 'proposal not passed!'); -} - -#[should_panic] -fn test_proposal_expiry() { - let gov_contract = deploy_governance(); - let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); - - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - let prop_id = dispatcher.submit_proposal(42, 1); - - //simulate passage of time - let current_timestamp = get_block_timestamp(); - let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(end_timestamp + 1, current_timestamp); - - let status = dispatcher.get_proposal_status(prop_id); -} - -#[should_panic] -fn test_vote_on_expired_proposal() { - let gov_contract = deploy_governance(); - let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); - - let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); - let prop_id = dispatcher.submit_proposal(42, 1); - - //simulate passage of time - let current_timestamp = get_block_timestamp(); - let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(end_timestamp + 1, current_timestamp); - - start_prank(CheatTarget::One(gov_contract_addr), first_address); - dispatcher.vote(prop_id, 1); -} - From 2884f0643d0f43024c40eb600e06e31f603dc092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Tue, 14 May 2024 17:43:28 +0000 Subject: [PATCH 22/39] Add minor fixes towards compilability --- tests/lib.cairo | 2 ++ tests/proposals_tests.cairo | 10 ++-------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/lib.cairo b/tests/lib.cairo index e574f18a..12bc39ff 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -1,3 +1,5 @@ mod add_options; mod basic; mod test_treasury; +mod proposals_tests; +mod airdrop_tests; diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index 63bf4d68..1b55595f 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -7,8 +7,7 @@ use snforge_std::{ BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget }; -mod setup; -use setup::{ +use governance::testing::setup::{ deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy }; use governance::contract::IGovernanceDispatcher; @@ -23,10 +22,6 @@ use starknet::get_block_timestamp; const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; -const first_address: ContractAddress = 0x1.try_into().unwrap(); -const second_address: ContractAddress = 0x2.try_into().unwrap(); -const admin_addr: ContractAddress = 0x3.try_into().unwrap(); - fn test_express_proposal() { let gov_contract = deploy_governance(); @@ -41,7 +36,7 @@ fn test_express_proposal() { start_prank(CheatTarget::One(gov_contract_addr), admin_addr); dispatcher.vote(prop_id, 1); - assert(dispatcher.get_proposal_status(prop_id) == 1, "proposal not passed!"); + assert!(dispatcher.get_proposal_status(prop_id) == 1, "proposal not passed!"); } #[should_panic] @@ -82,4 +77,3 @@ fn test_vote_on_expired_proposal() { start_prank(CheatTarget::One(gov_contract_addr), first_address); dispatcher.vote(prop_id, 1); } - From 89f902891d9f0ea02daf2055da9fbaf46c46e5c7 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Fri, 17 May 2024 13:15:48 +0000 Subject: [PATCH 23/39] Fix all proposals tests --- tests/proposals_tests.cairo | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index 1b55595f..ba163189 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -8,7 +8,7 @@ use snforge_std::{ }; use governance::testing::setup::{ - deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy + admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy }; use governance::contract::IGovernanceDispatcher; use governance::contract::IGovernanceDispatcherTrait; @@ -24,16 +24,16 @@ const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; fn test_express_proposal() { - let gov_contract = deploy_governance(); + let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); + let gov_contract = deploy_governance(token_contract.contract_address); let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); let prop_id = dispatcher.submit_proposal(42, 1); - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); dispatcher.vote(prop_id, 1); assert!(dispatcher.get_proposal_status(prop_id) == 1, "proposal not passed!"); @@ -41,39 +41,39 @@ fn test_express_proposal() { #[should_panic] fn test_proposal_expiry() { - let gov_contract = deploy_governance(); + let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); + let gov_contract = deploy_governance(token_contract.contract_address); let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); let prop_id = dispatcher.submit_proposal(42, 1); //simulate passage of time let current_timestamp = get_block_timestamp(); let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(end_timestamp + 1, gov_contract_addr.into()); + start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); let status = dispatcher.get_proposal_status(prop_id); } #[should_panic] fn test_vote_on_expired_proposal() { - let gov_contract = deploy_governance(); + let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); + let gov_contract = deploy_governance(token_contract.contract_address); let gov_contract_addr = gov_contract.contract_address; - let token_contract = deploy_and_distribute_gov_tokens(admin_addr); let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - start_prank(CheatTarget::One(gov_contract_addr), admin_addr); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); let prop_id = dispatcher.submit_proposal(42, 1); //simulate passage of time let current_timestamp = get_block_timestamp(); let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; - start_warp(end_timestamp + 1, gov_contract_addr.into()); + start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); - start_prank(CheatTarget::One(gov_contract_addr), first_address); + start_prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap()); dispatcher.vote(prop_id, 1); } From dc964b5b0e736ca384db6288bd3a3c69146f363e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Mon, 20 May 2024 15:25:38 +0000 Subject: [PATCH 24/39] Fix formatting --- tests/airdrop_tests.cairo | 2 ++ tests/proposals_tests.cairo | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/airdrop_tests.cairo b/tests/airdrop_tests.cairo index b5874641..4a9c1c8f 100644 --- a/tests/airdrop_tests.cairo +++ b/tests/airdrop_tests.cairo @@ -83,3 +83,5 @@ // contract.claim(claim_amount, old_proof_not_matching_new_root.span()); // // check fail : to do // } + + diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index ba163189..fc10d68a 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -8,7 +8,8 @@ use snforge_std::{ }; use governance::testing::setup::{ - admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy + admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, + test_vote_upgrade_root, check_if_healthy }; use governance::contract::IGovernanceDispatcher; use governance::contract::IGovernanceDispatcherTrait; From 72883ab6ec7f44fd724bc70c6a69bff42c2cc989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hobza?= <hobza.tomas@gmail.com> Date: Tue, 30 Apr 2024 09:51:37 +0200 Subject: [PATCH 25/39] Proposals Frontend (#66) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add: basic ui displaying proposals * feat: voting invocations * feat: :sparkles: new proposal form * feat: :sparkles: use async for proposal creation * fix: :bug: bad voting code * chore: :wastebasket: cleanup * feat: :sparkles: add logo * fix: :bug: wrong site title --------- Co-authored-by: Tomáš Hobza <xhobza03@vutbr.cz> --- frontend/src/components/NewProposalForm.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/src/components/NewProposalForm.tsx b/frontend/src/components/NewProposalForm.tsx index b9fdec66..a32d4f67 100644 --- a/frontend/src/components/NewProposalForm.tsx +++ b/frontend/src/components/NewProposalForm.tsx @@ -46,13 +46,11 @@ export default function NewProposalForm({ writeAsync() .then(() => { toast.success("Proposal submitted"); + setIsModalOpen(false); }) .catch((e) => { toast.error("Something went wrong"); console.error(e); - }) - .finally(() => { - setIsModalOpen(false); }); } @@ -71,7 +69,6 @@ export default function NewProposalForm({ id="#to_upgrade" className="w-full p-2 border rounded-lg border-slate-300" onChange={(e) => setToUpgrade(e.target.value)} - defaultValue={to_upgrade} > {/* Carmine 0 = amm, 1 = governance, 2 = CARM token, 3 = merkle tree root, 4 = no-op/signal vote */} <option value="0">amm</option> From b7f718e35c143b0bc67b11c80cb617c82d5ca5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hobza?= <hobza.tomas@gmail.com> Date: Fri, 3 May 2024 14:00:17 +0200 Subject: [PATCH 26/39] feat: default to_upgrade value (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomáš Hobza <xhobza03@vutbr.cz> --- frontend/src/components/NewProposalForm.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/NewProposalForm.tsx b/frontend/src/components/NewProposalForm.tsx index a32d4f67..b9fdec66 100644 --- a/frontend/src/components/NewProposalForm.tsx +++ b/frontend/src/components/NewProposalForm.tsx @@ -46,11 +46,13 @@ export default function NewProposalForm({ writeAsync() .then(() => { toast.success("Proposal submitted"); - setIsModalOpen(false); }) .catch((e) => { toast.error("Something went wrong"); console.error(e); + }) + .finally(() => { + setIsModalOpen(false); }); } @@ -69,6 +71,7 @@ export default function NewProposalForm({ id="#to_upgrade" className="w-full p-2 border rounded-lg border-slate-300" onChange={(e) => setToUpgrade(e.target.value)} + defaultValue={to_upgrade} > {/* Carmine 0 = amm, 1 = governance, 2 = CARM token, 3 = merkle tree root, 4 = no-op/signal vote */} <option value="0">amm</option> From d622ff9cb49077d72393c2f3979a6d9156e44919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Tue, 14 May 2024 14:11:52 +0200 Subject: [PATCH 27/39] Update frontend domain to konoha.vote --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 29d45968..dd691358 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ We're rewarding contributors with fiat and STRK tokens through [OnlyDust](https: ## Frontend -A demo frontend accessing a deployment on Sepolia is available at http://34.171.48.97/ +A demo frontend accessing a deployment on Sepolia is available at https://konoha.vote/ ## Proposal notification service From fc71439bebc1968511d56f939897e42cf4d7fc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Tue, 14 May 2024 14:31:08 +0000 Subject: [PATCH 28/39] Rename package from 'governance' to 'konoha' --- Scarb.lock | 4 ++-- Scarb.toml | 6 +++--- src/airdrop.cairo | 15 +++++++-------- src/contract.cairo | 16 ++++++++-------- src/options.cairo | 18 +++++++++--------- src/proposals.cairo | 21 ++++++++++----------- src/traits.cairo | 4 ++-- src/treasury.cairo | 6 +++--- src/upgrades.cairo | 26 +++++++++++++------------- src/vesting.cairo | 4 ++-- tests/add_options.cairo | 10 ++++------ tests/basic.cairo | 12 ++++++------ tests/test_treasury.cairo | 6 ++---- 13 files changed, 71 insertions(+), 77 deletions(-) diff --git a/Scarb.lock b/Scarb.lock index f0cb3619..4af793f8 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -4,10 +4,10 @@ version = 1 [[package]] name = "cubit" version = "1.3.0" -source = "git+https://github.com/influenceth/cubit.git#62756082bf2555d7ab25c69d9c7bc30574ff1ce8" +source = "git+https://github.com/influenceth/cubit.git#8eacc2b1d952d6266f9725776445c7fb97453403" [[package]] -name = "governance" +name = "konoha" version = "0.3.0" dependencies = [ "cubit", diff --git a/Scarb.toml b/Scarb.toml index 1b813207..f04f99f7 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,5 +1,5 @@ [package] -name = "governance" +name = "konoha" description = "A flexible monolithic governance contract, developed for use with Carmine Options AMM" version = "0.3.0" cairo-version = "2.6.3" @@ -21,5 +21,5 @@ block_id.tag = "Latest" name = "SEPOLIA" url = "http://34.22.208.73:6062/v0_7" block_id.tag = "Latest" - -RUST_BACKTRACE=1 + +RUST_BACKTRACE = 1 diff --git a/src/airdrop.cairo b/src/airdrop.cairo index b9a934ff..fc0bfee6 100644 --- a/src/airdrop.cairo +++ b/src/airdrop.cairo @@ -11,23 +11,22 @@ trait IAirdrop<TContractState> { #[starknet::component] mod airdrop { - use governance::contract::IGovernance; + use konoha::contract::IGovernance; use array::ArrayTrait; use hash::LegacyHash; use traits::Into; use starknet::ContractAddressIntoFelt252; use starknet::ContractAddress; - //use starknet::event::EventEmitter; use traits::TryInto; use option::OptionTrait; - use governance::merkle_tree::MerkleTree; - use governance::merkle_tree::MerkleTreeTrait; + use konoha::merkle_tree::MerkleTree; + use konoha::merkle_tree::MerkleTreeTrait; - use governance::contract::Governance; - use governance::contract::Governance::ContractState; - use governance::traits::IGovernanceTokenDispatcher; - use governance::traits::IGovernanceTokenDispatcherTrait; + use konoha::contract::Governance; + use konoha::contract::Governance::ContractState; + use konoha::traits::IGovernanceTokenDispatcher; + use konoha::traits::IGovernanceTokenDispatcherTrait; #[storage] struct Storage { diff --git a/src/contract.cairo b/src/contract.cairo index 32f47ef8..cd2db034 100644 --- a/src/contract.cairo +++ b/src/contract.cairo @@ -2,7 +2,7 @@ // When Components arrive in Cairo 2.?, it will be refactored to take advantage of them. Random change to rerun CI use starknet::ContractAddress; -use governance::types::{ContractType, PropDetails, VoteStatus}; +use konoha::types::{ContractType, PropDetails, VoteStatus}; #[starknet::interface] trait IGovernance<TContractState> { @@ -25,13 +25,13 @@ trait IGovernance<TContractState> { #[starknet::contract] mod Governance { - use governance::types::BlockNumber; - use governance::types::VoteStatus; - use governance::types::ContractType; - use governance::types::PropDetails; - use governance::proposals::proposals as proposals_component; - use governance::upgrades::upgrades as upgrades_component; - use governance::airdrop::airdrop as airdrop_component; + use konoha::types::BlockNumber; + use konoha::types::VoteStatus; + use konoha::types::ContractType; + use konoha::types::PropDetails; + use konoha::proposals::proposals as proposals_component; + use konoha::upgrades::upgrades as upgrades_component; + use konoha::airdrop::airdrop as airdrop_component; use starknet::ContractAddress; diff --git a/src/options.cairo b/src/options.cairo index 8c45bb72..86d2b84b 100644 --- a/src/options.cairo +++ b/src/options.cairo @@ -3,7 +3,7 @@ // – first generating FutureOption, then generating everything from Pragma data mod Options { - use governance::contract::IGovernance; + use konoha::contract::IGovernance; use traits::{Into, TryInto}; use array::{ArrayTrait, SpanTrait}; use option::OptionTrait; @@ -20,22 +20,22 @@ mod Options { use cubit::f128::types::{Fixed, FixedTrait}; - use governance::contract::Governance::{amm_address, proposal_initializer_run}; - use governance::constants::{ + use konoha::contract::konoha::{amm_address, proposal_initializer_run}; + use konoha::constants::{ OPTION_CALL, OPTION_PUT, TRADE_SIDE_LONG, TRADE_SIDE_SHORT, OPTION_TOKEN_CLASS_HASH }; - use governance::traits::{ + use konoha::traits::{ IAMMDispatcher, IAMMDispatcherTrait, IOptionTokenDispatcher, IOptionTokenDispatcherTrait }; - use governance::types::OptionSide; - use governance::contract::Governance; - use governance::types::OptionType; - use governance::contract::Governance::proposal_initializer_runContractMemberStateTrait; + use konoha::types::OptionSide; + use konoha::contract::Governance; + use konoha::types::OptionType; + use konoha::contract::konoha::proposal_initializer_runContractMemberStateTrait; fn add_options(mut options: Span<FutureOption>) { // TODO use block hash from block_hash syscall as salt // actually doable with the new syscall let governance_address = get_contract_address(); - let state = Governance::unsafe_new_contract_state(); + let state = konoha::unsafe_new_contract_state(); let amm_address = state.get_amm_address(); loop { match options.pop_front() { diff --git a/src/proposals.cairo b/src/proposals.cairo index 5ada97f9..beabcd9a 100644 --- a/src/proposals.cairo +++ b/src/proposals.cairo @@ -1,6 +1,6 @@ // Proposals component. Does not depend on anything. Holds governance token address. -use governance::types::{ContractType, PropDetails, VoteStatus}; +use konoha::types::{ContractType, PropDetails, VoteStatus}; use starknet::ContractAddress; #[starknet::interface] @@ -23,7 +23,7 @@ trait IProposals<TContractState> { #[starknet::component] mod proposals { - use governance::contract::IGovernance; + use konoha::contract::IGovernance; use traits::TryInto; use option::OptionTrait; use traits::Into; @@ -52,15 +52,14 @@ mod proposals { use starknet::class_hash::class_hash_try_from_felt252; use starknet::contract_address::contract_address_to_felt252; - use governance::types::BlockNumber; - use governance::types::ContractType; - use governance::types::PropDetails; - use governance::types::VoteStatus; - use governance::types::CustomProposalConfig; - use governance::traits::IERC20Dispatcher; - use governance::traits::IERC20DispatcherTrait; - use governance::traits::get_governance_token_address_self; - use governance::constants; + use konoha::types::BlockNumber; + use konoha::types::ContractType; + use konoha::types::PropDetails; + use konoha::types::VoteStatus; + use konoha::traits::IERC20Dispatcher; + use konoha::traits::IERC20DispatcherTrait; + use konoha::traits::get_governance_token_address_self; + use konoha::constants; #[storage] struct Storage { diff --git a/src/traits.cairo b/src/traits.cairo index 584f2be0..cece8097 100644 --- a/src/traits.cairo +++ b/src/traits.cairo @@ -1,7 +1,7 @@ use starknet::{ClassHash, ContractAddress}; -use governance::types::OptionSide; -use governance::types::OptionType; +use konoha::types::OptionSide; +use konoha::types::OptionType; use core::starknet::SyscallResultTrait; use cubit::f128::types::{Fixed, FixedTrait}; diff --git a/src/treasury.cairo b/src/treasury.cairo index 7ba3ca29..46e28a3b 100644 --- a/src/treasury.cairo +++ b/src/treasury.cairo @@ -1,5 +1,5 @@ use starknet::ContractAddress; -use governance::types::OptionType; +use konoha::types::OptionType; #[starknet::interface] trait ITreasury<TContractState> { @@ -39,8 +39,8 @@ mod Treasury { use openzeppelin::upgrades::upgradeable::UpgradeableComponent; use openzeppelin::upgrades::interface::IUpgradeable; use starknet::{ContractAddress, get_caller_address, get_contract_address, ClassHash}; - use governance::airdrop::{IAirdropDispatcher, IAirdropDispatcherTrait}; - use governance::traits::{ + use konoha::airdrop::{IAirdropDispatcher, IAirdropDispatcherTrait}; + use konoha::traits::{ IERC20Dispatcher, IERC20DispatcherTrait, IAMMDispatcher, IAMMDispatcherTrait }; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/src/upgrades.cairo b/src/upgrades.cairo index b8545bf0..23311814 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -19,19 +19,19 @@ mod upgrades { use starknet::ContractAddress; use starknet::class_hash; - use governance::types::{CustomProposalConfig, PropDetails}; - use governance::contract::Governance; - use governance::contract::Governance::ContractState; + use konoha::types::PropDetails; + use konoha::contract::Governance; + use konoha::contract::Governance::ContractState; - use governance::proposals::proposals as proposals_component; - use governance::proposals::proposals::ProposalsImpl; - use governance::airdrop::airdrop as airdrop_component; - use governance::traits::IAMMDispatcher; - use governance::traits::IAMMDispatcherTrait; - use governance::traits::IGovernanceTokenDispatcher; - use governance::traits::IGovernanceTokenDispatcherTrait; - use governance::traits::get_amm_address_self; - use governance::traits::get_governance_token_address_self; + use konoha::proposals::proposals as proposals_component; + use konoha::proposals::proposals::ProposalsImpl; + use konoha::airdrop::airdrop as airdrop_component; + use konoha::traits::IAMMDispatcher; + use konoha::traits::IAMMDispatcherTrait; + use konoha::traits::IGovernanceTokenDispatcher; + use konoha::traits::IGovernanceTokenDispatcherTrait; + use konoha::traits::get_amm_address_self; + use konoha::traits::get_governance_token_address_self; #[storage] struct Storage { @@ -64,7 +64,7 @@ mod upgrades { let status = proposals_comp .get_proposal_status( prop_id - ); // needs use governance::proposals::proposals::ProposalsImpl; + ); // needs use konoha::proposals::proposals::ProposalsImpl; assert(status == 1, 'prop not passed'); let applied = self.proposal_applied.read(prop_id); assert(!applied, 'Proposal already applied'); diff --git a/src/vesting.cairo b/src/vesting.cairo index e0aecfe3..f62087e0 100644 --- a/src/vesting.cairo +++ b/src/vesting.cairo @@ -26,8 +26,8 @@ trait IVesting<TContractState> { mod vesting { use starknet::syscalls::get_block_timestamp; - use governance::traits::IGovernanceTokenDispatcher; - use governance::traits::IGovernanceTokenDispatcherTrait; + use konoha::traits::IGovernanceTokenDispatcher; + use konoha::traits::IGovernanceTokenDispatcherTrait; #[storage] struct Storage { diff --git a/tests/add_options.cairo b/tests/add_options.cairo index 488efb23..7dd985a8 100644 --- a/tests/add_options.cairo +++ b/tests/add_options.cairo @@ -1,11 +1,9 @@ use super::basic::submit_44_signal_proposals; -use governance::traits::IAMM; -use governance::contract::IGovernanceDispatcher; -use governance::contract::IGovernanceDispatcherTrait; -use governance::traits::{ - IAMMDispatcher, IAMMDispatcherTrait, IERC20Dispatcher, IERC20DispatcherTrait -}; +use konoha::traits::IAMM; +use konoha::contract::IGovernanceDispatcher; +use konoha::contract::IGovernanceDispatcherTrait; +use konoha::traits::{IAMMDispatcher, IAMMDispatcherTrait, IERC20Dispatcher, IERC20DispatcherTrait}; use starknet::{ContractAddress, get_block_timestamp}; diff --git a/tests/basic.cairo b/tests/basic.cairo index 04f238d3..a6eb631c 100644 --- a/tests/basic.cairo +++ b/tests/basic.cairo @@ -4,12 +4,12 @@ use debug::PrintTrait; use starknet::ContractAddress; use snforge_std::{BlockId, declare, ContractClassTrait, ContractClass, start_prank, CheatTarget}; -use governance::contract::IGovernanceDispatcher; -use governance::contract::IGovernanceDispatcherTrait; -use governance::proposals::IProposalsDispatcher; -use governance::proposals::IProposalsDispatcherTrait; -use governance::upgrades::IUpgradesDispatcher; -use governance::upgrades::IUpgradesDispatcherTrait; +use konoha::contract::IGovernanceDispatcher; +use konoha::contract::IGovernanceDispatcherTrait; +use konoha::proposals::IProposalsDispatcher; +use konoha::proposals::IProposalsDispatcherTrait; +use konoha::upgrades::IUpgradesDispatcher; +use konoha::upgrades::IUpgradesDispatcherTrait; //#[test] //#[fork(url: "https://rpc.starknet-testnet.lava.build", block_id: BlockId::Number(904597))] diff --git a/tests/test_treasury.cairo b/tests/test_treasury.cairo index 452944e2..4e306ae7 100644 --- a/tests/test_treasury.cairo +++ b/tests/test_treasury.cairo @@ -21,10 +21,8 @@ use snforge_std::{ BlockId, declare, ContractClassTrait, ContractClass, prank, CheatSpan, CheatTarget, start_roll, stop_roll, }; -use governance::treasury::{ITreasuryDispatcher, ITreasuryDispatcherTrait}; -use governance::traits::{ - IERC20Dispatcher, IERC20DispatcherTrait, IAMMDispatcher, IAMMDispatcherTrait -}; +use konoha::treasury::{ITreasuryDispatcher, ITreasuryDispatcherTrait}; +use konoha::traits::{IERC20Dispatcher, IERC20DispatcherTrait, IAMMDispatcher, IAMMDispatcherTrait}; use openzeppelin::access::ownable::interface::{ IOwnableTwoStep, IOwnableTwoStepDispatcherTrait, IOwnableTwoStepDispatcher }; From 4620dd0d74eacaa880893936f9f15bdd95bafee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Mon, 20 May 2024 14:57:06 +0200 Subject: [PATCH 29/39] Add contributor guidelines --- CONTRIBUTING.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d777cc3e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# Contributor Guidelines + +1. Task Claiming + - Comment: 'I would like to take this task,' including the estimated delivery timeline (start and completion dates) and a brief summary of relevant skills (required for complex tasks). + - Join the contributors' Telegram group for updates and discussions. +2. Task Assignment + - Basic tasks: Assigned on a first-come, first-served basis. No further assignment required. + - Complex tasks: Prospective assignees must outline their approach to the task. Assignments will be based on these proposals to ensure optimal match and prioritization. +4. Initial Commit Requirement + - If no commits are made or the assignee is unreachable within 48 hours post-assignment, we reserve the right to reassign the task. + - We also reserve the right to reassign tasks if it becomes clear they cannot be completed by the hackathon's end. +5. Submission Guidelines + - Submit a pull request (PR) from the forked repository. + - Ensure to rebase on the current master branch before creating the PR. + +### Communication + +* For questions, contact us via this GitHub (response might be slower) or Telegram ( https://t.me/konoha_dev for a faster response). From 2a12029c969f6183f0274c39df667cb26e01ef73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Mon, 20 May 2024 15:00:35 +0200 Subject: [PATCH 30/39] Update README.md with contributing info --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dd691358..299f1c47 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,9 @@ Currently, this is being developed mainly with community-wide use in mind. Reach out to us via [Telegram](https://t.me/+_BpaFo4iarszZmQ0) -## Contribute and earn +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for contributor guidelines We're rewarding contributors with fiat and STRK tokens through [OnlyDust](https://app.onlydust.com/p/carmine-options-amm). From 32dbf371d4f1fa5b7afb0f5922c1e0a5d8adc2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Wed, 22 May 2024 14:46:04 +0200 Subject: [PATCH 31/39] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d777cc3e..0cc61297 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ - Comment: 'I would like to take this task,' including the estimated delivery timeline (start and completion dates) and a brief summary of relevant skills (required for complex tasks). - Join the contributors' Telegram group for updates and discussions. 2. Task Assignment - - Basic tasks: Assigned on a first-come, first-served basis. No further assignment required. + - Easy/Medium tasks: Assigned on a first-come, first-served basis. No further assignment required. - Complex tasks: Prospective assignees must outline their approach to the task. Assignments will be based on these proposals to ensure optimal match and prioritization. 4. Initial Commit Requirement - If no commits are made or the assignee is unreachable within 48 hours post-assignment, we reserve the right to reassign the task. From 7b4cb3c2a4075cd8265d5094995c2ae20dac2541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Wed, 22 May 2024 20:16:50 +0200 Subject: [PATCH 32/39] Add mdbook scaffolding (#75) * Add mdbook stub * Update license to Apache 2.0 * Add some docs --- LICENSE | 222 ++++++++++++++++++-- README.md | 2 +- docs/.gitignore | 1 + docs/README.md | 6 + docs/book.toml | 6 + CONTRIBUTING.md => docs/src/CONTRIBUTING.md | 6 +- docs/src/SUMMARY.md | 14 ++ docs/src/about.md | 17 ++ docs/src/dev/environ.md | 5 + docs/src/dev/testing.md | 9 + docs/src/proposals.md | 1 + docs/src/staking.md | 1 + docs/src/treasury.md | 1 + docs/src/upgrades.md | 1 + 14 files changed, 268 insertions(+), 24 deletions(-) create mode 100644 docs/.gitignore create mode 100644 docs/README.md create mode 100644 docs/book.toml rename CONTRIBUTING.md => docs/src/CONTRIBUTING.md (78%) create mode 100644 docs/src/SUMMARY.md create mode 100644 docs/src/about.md create mode 100644 docs/src/dev/environ.md create mode 100644 docs/src/dev/testing.md create mode 100644 docs/src/proposals.md create mode 100644 docs/src/staking.md create mode 100644 docs/src/treasury.md create mode 100644 docs/src/upgrades.md diff --git a/LICENSE b/LICENSE index 52b5ec39..80afabb2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) 2023 Carmine Finance - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2024] [Carmine Finance] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index 299f1c47..b6ea79b8 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Reach out to us via [Telegram](https://t.me/+_BpaFo4iarszZmQ0) ## Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md) for contributor guidelines +See [CONTRIBUTING.md](docs/src/CONTRIBUTING.md) for contributor guidelines We're rewarding contributors with fiat and STRK tokens through [OnlyDust](https://app.onlydust.com/p/carmine-options-amm). diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..7585238e --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +book diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..d957fb1b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +# Writing docs + +1. Install mdBook according to [instructions](https://rust-lang.github.io/mdBook/guide/installation.html) +2. In directory docs/, run `mdbook serve`. Open a browser at http://127.0.0.1:3000 and you can browse the book at its current state. + +To write, add and/or edit Markdown files in `docs/src`. \ No newline at end of file diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 00000000..f72742a9 --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["Ondřej Sojka", "Konoha Contributors"] +language = "en" +multilingual = false +src = "src" +title = "Konoha Book" diff --git a/CONTRIBUTING.md b/docs/src/CONTRIBUTING.md similarity index 78% rename from CONTRIBUTING.md rename to docs/src/CONTRIBUTING.md index 0cc61297..dcb2dcdb 100644 --- a/CONTRIBUTING.md +++ b/docs/src/CONTRIBUTING.md @@ -1,5 +1,7 @@ # Contributor Guidelines +We are now focusing on the ODHack hackathon, new issues will be released on hackathon start. + 1. Task Claiming - Comment: 'I would like to take this task,' including the estimated delivery timeline (start and completion dates) and a brief summary of relevant skills (required for complex tasks). - Join the contributors' Telegram group for updates and discussions. @@ -8,11 +10,11 @@ - Complex tasks: Prospective assignees must outline their approach to the task. Assignments will be based on these proposals to ensure optimal match and prioritization. 4. Initial Commit Requirement - If no commits are made or the assignee is unreachable within 48 hours post-assignment, we reserve the right to reassign the task. - - We also reserve the right to reassign tasks if it becomes clear they cannot be completed by the hackathon's end. + - We also reserve the right to reassign tasks if it becomes clear they cannot be completed by the ODHack's end. 5. Submission Guidelines - Submit a pull request (PR) from the forked repository. - Ensure to rebase on the current master branch before creating the PR. ### Communication -* For questions, contact us via this GitHub (response might be slower) or Telegram ( https://t.me/konoha_dev for a faster response). +* For questions, contact us via GitHub (response might be slower) or [Telegram](https://t.me/konoha_dev) for a faster response. diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md new file mode 100644 index 00000000..b540713c --- /dev/null +++ b/docs/src/SUMMARY.md @@ -0,0 +1,14 @@ +# Summary + +[About Konoha](./about.md) + +# Feature Guide +- [Proposals](./proposals.md) +- [Upgrades](./upgrades.md) +- [Treasury](./treasury.md) +- [Staking](./staking.md) + +# Development +- [Contributor guide](./CONTRIBUTING.md) +- [Development environment](./dev/environ.md) +- [Testing (Cairo code)](./dev/testing.md) \ No newline at end of file diff --git a/docs/src/about.md b/docs/src/about.md new file mode 100644 index 00000000..33865be5 --- /dev/null +++ b/docs/src/about.md @@ -0,0 +1,17 @@ +# About Konoha + +Many projects on Starknet will need the same functionality: DAO-like governance, upgrades, token vesting, staking and airdrops, treasury management, etc. On Ethereum, they can use adapt open-source solutions such as [Compound Governance](https://github.com/compound-finance/compound-protocol/tree/master/contracts/Governance). No such solution currently exists for Starknet (with the noble exception of [Ekubo governance](https://github.com/EkuboProtocol/governance/tree/main/src)). + +Originally, it was a rewrite of [Carmine Governance contracts](https://github.com/CarmineOptions/carmine-protocol/tree/master/contracts/governance) to Cairo 1.0, while also making them generic and useful for the rest of the community. + +Currently, this is being developed mainly with community-wide use in mind. + +## Who is Konoha for + +If you're a project on Starknet looking to do any of: +- decentralize and be governed by your tokenholders +- govern a treasury +- distribute rewards or protocol token +- support staking of your protocol token + +Please reach out to us a https://t.me/konoha_dev and share more on your specific usecase. The sooner you do, the higher the chance that we'll be able to build for your usecase specifically. \ No newline at end of file diff --git a/docs/src/dev/environ.md b/docs/src/dev/environ.md new file mode 100644 index 00000000..7776cd31 --- /dev/null +++ b/docs/src/dev/environ.md @@ -0,0 +1,5 @@ +# Development environment + +We support and keep updated a [Devcontainer](https://containers.dev/) in `.devcontainer/devcontainer.json`. + +To develop, open the cloned repository in VSCode and invoke the command *Rebuild and Reopen in Devcontainer*. (Ctrl/Command+Shift+P and type rebuild). \ No newline at end of file diff --git a/docs/src/dev/testing.md b/docs/src/dev/testing.md new file mode 100644 index 00000000..86c68709 --- /dev/null +++ b/docs/src/dev/testing.md @@ -0,0 +1,9 @@ +# Testing + +All Cairo code must be tested for the PR to be approved and merged. Tests must cover all of the functionality and edge cases. + +## Adding a new tests file + +1. Create a new file, such as `test_staking.cairo` +2. Update `tests/lib.cairo` and add `mod test_staking;` Don't forget to sort the module names alphabetically. +3. Refer to the [Starknet Foundry Book](https://foundry-rs.github.io/starknet-foundry/) for reference on `snforge` which we use for tests. \ No newline at end of file diff --git a/docs/src/proposals.md b/docs/src/proposals.md new file mode 100644 index 00000000..2195a7f4 --- /dev/null +++ b/docs/src/proposals.md @@ -0,0 +1 @@ +# Proposals diff --git a/docs/src/staking.md b/docs/src/staking.md new file mode 100644 index 00000000..abe5cd84 --- /dev/null +++ b/docs/src/staking.md @@ -0,0 +1 @@ +# Staking diff --git a/docs/src/treasury.md b/docs/src/treasury.md new file mode 100644 index 00000000..4cd0ac5a --- /dev/null +++ b/docs/src/treasury.md @@ -0,0 +1 @@ +# Treasury diff --git a/docs/src/upgrades.md b/docs/src/upgrades.md new file mode 100644 index 00000000..c96e9252 --- /dev/null +++ b/docs/src/upgrades.md @@ -0,0 +1 @@ +# Upgrades From 7cf23cddc561cbeab089ef17ccdba3d7dc86cbc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Thu, 23 May 2024 11:13:32 +0200 Subject: [PATCH 33/39] Add custom proposal implementation (#64) * Add custom proposal implementation Lacks setting of custom proposal configuration during deployment * Add arbitrary proposal * Polish apply_passed_proposal * Polish scarb fmt * Cherry pick setup.cairo from 1fab54f * Move test setup to src/ * Remove unrelated functions from setup.cairo * Fix setup * Polish tests * Fix import naming * Add addition of custom proposal --- src/proposals.cairo | 30 +++++++++++++++++++++++++++++- src/testing/setup.cairo | 14 +++++++------- src/upgrades.cairo | 2 +- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/proposals.cairo b/src/proposals.cairo index beabcd9a..7f3c294c 100644 --- a/src/proposals.cairo +++ b/src/proposals.cairo @@ -1,6 +1,6 @@ // Proposals component. Does not depend on anything. Holds governance token address. -use konoha::types::{ContractType, PropDetails, VoteStatus}; +use konoha::types::{ContractType, PropDetails, VoteStatus, CustomProposalConfig}; use starknet::ContractAddress; #[starknet::interface] @@ -19,6 +19,7 @@ trait IProposals<TContractState> { fn submit_custom_proposal( ref self: TContractState, custom_proposal_type: u32, calldata: Span<felt252> ) -> u32; + fn get_custom_proposal_type(self: @TContractState, i: u32) -> CustomProposalConfig; } #[starknet::component] @@ -56,6 +57,7 @@ mod proposals { use konoha::types::ContractType; use konoha::types::PropDetails; use konoha::types::VoteStatus; + use konoha::types::CustomProposalConfig; use konoha::traits::IERC20Dispatcher; use konoha::traits::IERC20DispatcherTrait; use konoha::traits::get_governance_token_address_self; @@ -241,6 +243,26 @@ mod proposals { let res: u256 = (caller_balance * constants::NEW_PROPOSAL_QUORUM).into(); assert(total_supply < res, 'not enough tokens to submit'); } + + fn _find_free_custom_proposal_type(self: @ComponentState<TContractState>) -> u32 { + let mut i = 0; + let mut res = self.custom_proposal_type.read(i); + while (res.target.is_non_zero()) { + i += 1; + res = self.custom_proposal_type.read(i); + }; + i + } + + fn add_custom_proposal_config( + ref self: ComponentState<TContractState>, config: CustomProposalConfig + ) -> u32 { + let idx = self._find_free_custom_proposal_type(); + assert(config.target.is_non_zero(), 'target must be nonzero'); + assert(config.selector.is_non_zero(), 'selector must be nonzero'); + self.custom_proposal_type.write(idx, config); + idx + } } #[embeddable_as(ProposalsImpl)] @@ -493,5 +515,11 @@ mod proposals { return constants::MINUS_ONE; // yay_tally < nay_tally } } + + fn get_custom_proposal_type( + self: @ComponentState<TContractState>, i: u32 + ) -> CustomProposalConfig { + self.custom_proposal_type.read(i) + } } } diff --git a/src/testing/setup.cairo b/src/testing/setup.cairo index b880882d..7e8507b7 100644 --- a/src/testing/setup.cairo +++ b/src/testing/setup.cairo @@ -9,13 +9,13 @@ use snforge_std::{ }; -use governance::contract::IGovernanceDispatcher; -use governance::contract::IGovernanceDispatcherTrait; -use governance::proposals::IProposalsDispatcher; -use governance::proposals::IProposalsDispatcherTrait; -use governance::upgrades::IUpgradesDispatcher; -use governance::upgrades::IUpgradesDispatcherTrait; -use governance::constants; +use konoha::contract::IGovernanceDispatcher; +use konoha::contract::IGovernanceDispatcherTrait; +use konoha::proposals::IProposalsDispatcher; +use konoha::proposals::IProposalsDispatcherTrait; +use konoha::upgrades::IUpgradesDispatcher; +use konoha::upgrades::IUpgradesDispatcherTrait; +use konoha::constants; use openzeppelin::token::erc20::interface::IERC20; use starknet::get_block_timestamp; diff --git a/src/upgrades.cairo b/src/upgrades.cairo index 23311814..5e33f541 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -19,7 +19,7 @@ mod upgrades { use starknet::ContractAddress; use starknet::class_hash; - use konoha::types::PropDetails; + use konoha::types::{CustomProposalConfig, PropDetails}; use konoha::contract::Governance; use konoha::contract::Governance::ContractState; From 9837f6984d748b820c96896a2fadeb322238fc32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Thu, 23 May 2024 11:22:51 +0200 Subject: [PATCH 34/39] Remove mentions of Carmine in this repository (#73) * Update Scarb.toml, add [lib] * Add custom proposal implementation Lacks setting of custom proposal configuration during deployment * Add arbitrary proposal * Polish apply_passed_proposal * Polish scarb fmt * Cherry pick setup.cairo from 1fab54f * Move test setup to src/ * Remove unrelated functions from setup.cairo * Fix setup * Polish tests * Fix import naming * Add addition of custom proposal * Remove part of Carmine code * Remove rest of Carmine stuff * Polish with scarb fmt * Bump version to 0.4.0 * Fix imports in tests * Remove unused test from lib.cairo * Remove cubit as dependency * Update package description * Update error message to not mention CARM * Move snforge_std to dev-dependency * Update snforge_std to v0.23.0 * Update snforge in CI * Trigger CI * Format --- .devcontainer/devcontainer.json | 9 +- .github/workflows/ci.yml | 2 +- Scarb.lock | 12 +- Scarb.toml | 15 +- src/amm_types/basic.cairo | 16 -- src/constants.cairo | 13 -- src/contract.cairo | 6 - src/lib.cairo | 4 +- src/options.cairo | 264 ------------------------------ src/proposals.cairo | 7 +- src/testing/setup.cairo | 13 +- src/traits.cairo | 272 +------------------------------ src/treasury.cairo | 7 +- src/treasury_types/carmine.cairo | 62 +++++++ src/types.cairo | 2 - src/upgrades.cairo | 15 +- tests/add_options.cairo | 71 -------- tests/basic.cairo | 2 +- tests/lib.cairo | 1 - tests/test_treasury.cairo | 8 +- 20 files changed, 103 insertions(+), 698 deletions(-) delete mode 100644 src/amm_types/basic.cairo delete mode 100644 src/options.cairo create mode 100644 src/treasury_types/carmine.cairo delete mode 100644 tests/add_options.cairo diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6ae19b24..46d09606 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,15 +13,12 @@ // "type": "volume" // } // ] - // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, - // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v 2.6.3", + "postCreateCommand": "curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v 2.6.3; curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh; snfoundryup -v 0.23.0", "customizations": { "vscode": { "extensions": [ @@ -29,10 +26,8 @@ ] } } - // Configure tool-specific properties. // "customizations": {}, - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "root" -} +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9f3bca7..6cbfff96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: env: SCARB_VERSION: 2.6.4 - FOUNDRY_VERSION: 0.20.1 + FOUNDRY_VERSION: 0.23.0 jobs: build: diff --git a/Scarb.lock b/Scarb.lock index 4af793f8..86b050a7 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -1,16 +1,10 @@ # Code generated by scarb DO NOT EDIT. version = 1 -[[package]] -name = "cubit" -version = "1.3.0" -source = "git+https://github.com/influenceth/cubit.git#8eacc2b1d952d6266f9725776445c7fb97453403" - [[package]] name = "konoha" -version = "0.3.0" +version = "0.4.0" dependencies = [ - "cubit", "openzeppelin", "snforge_std", ] @@ -22,5 +16,5 @@ source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.10.0#d7 [[package]] name = "snforge_std" -version = "0.20.1" -source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.20.1#fea2db8f2b20148cc15ee34b08de12028eb42942" +version = "0.23.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.23.0#f2bff8f796763ada77fe6033ec1b034ceee22abd" diff --git a/Scarb.toml b/Scarb.toml index f04f99f7..9e596461 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,14 +1,19 @@ [package] name = "konoha" -description = "A flexible monolithic governance contract, developed for use with Carmine Options AMM" -version = "0.3.0" +description = "Flexible monolithic governance components for Starknet" +version = "0.4.0" cairo-version = "2.6.3" [dependencies] -cubit = { git = "https://github.com/influenceth/cubit.git", commit = "62756082bf2555d7ab25c69d9c7bc30574ff1ce8" } -starknet = ">=1.3.0" -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.20.1" } +starknet = ">=2.0.0" openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.10.0" } +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.23.0" } + + +# can be fixed by doing import super::testing from tests +# [dev-dependencies] sadly can't use this because we have testing in src/ + +[lib] [[target.starknet-contract]] diff --git a/src/amm_types/basic.cairo b/src/amm_types/basic.cairo deleted file mode 100644 index ad315278..00000000 --- a/src/amm_types/basic.cairo +++ /dev/null @@ -1,16 +0,0 @@ -use cubit::f128::types::fixed::{Fixed, FixedTrait}; -use starknet::ContractAddress; -use core::option::OptionTrait; - -type LPTAddress = ContractAddress; -type OptionSide = u8; -type OptionType = u8; -type Timestamp = u64; // In seconds, Block timestamps are also u64 - -type Int = u128; - -type Maturity = felt252; - -type Volatility = Fixed; -type Strike = Fixed; - diff --git a/src/constants.cairo b/src/constants.cairo index 123dff00..17480f85 100644 --- a/src/constants.cairo +++ b/src/constants.cairo @@ -3,10 +3,6 @@ const NEW_PROPOSAL_QUORUM: u128 = const QUORUM: u128 = 10; // 1/10 of totalSupply required to participate to pass const MINUS_ONE: felt252 = 0x800000000000011000000000000000000000000000000000000000000000000; const TEAM_TOKEN_BALANCE: u128 = 1000000000000000000; -const OPTION_CALL: felt252 = 0; -const OPTION_PUT: felt252 = 1; -const TRADE_SIDE_LONG: felt252 = 0; -const TRADE_SIDE_SHORT: felt252 = 1; const PROPOSAL_VOTING_SECONDS: u64 = consteval_int!(60 * 60 * 24 * 7); @@ -15,12 +11,3 @@ const PROPOSAL_VOTING_SECONDS: u64 = consteval_int!(60 * 60 * 24 * 7); const USDC_ADDRESS: felt252 = 0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8; const ETH_ADDRESS: felt252 = 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7; const BTC_ADDRESS: felt252 = 0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac; - -// CLASS HASHES - -// corresponds to commit 7b7db57419fdb25b93621fbea6a845005f7725d0 in protocol-cairo1 repo, branch audit-fixes -const LP_TOKEN_CLASS_HASH: felt252 = - 0x06d15bc862ce48375ec98fea84d76ca67b7ac5978d80c848fa5496108783fbc2; -const AMM_CLASS_HASH: felt252 = 0x045fb686c8875f31966e7308d71c03e9ae78f9566a61870a2b616dc225dd3313; -const OPTION_TOKEN_CLASS_HASH: felt252 = - 0x07fc0b6ecc96a698cdac8c4ae447816d73bffdd9603faacffc0a8047149d02ed; diff --git a/src/contract.cairo b/src/contract.cairo index cd2db034..4c624e78 100644 --- a/src/contract.cairo +++ b/src/contract.cairo @@ -13,7 +13,6 @@ trait IGovernance<TContractState> { // UPGRADES fn get_governance_token_address(self: @TContractState) -> ContractAddress; - fn get_amm_address(self: @TContractState) -> ContractAddress; // fn apply_passed_proposal(ref self: TContractState, prop_id: felt252); // AIRDROPS @@ -53,7 +52,6 @@ mod Governance { struct Storage { proposal_initializer_run: LegacyMap::<u64, bool>, governance_token_address: ContractAddress, - amm_address: ContractAddress, #[substorage(v0)] proposals: proposals_component::Storage, #[substorage(v0)] @@ -99,9 +97,5 @@ mod Governance { fn get_governance_token_address(self: @ContractState) -> ContractAddress { self.governance_token_address.read() } - - fn get_amm_address(self: @ContractState) -> ContractAddress { - self.amm_address.read() - } } } diff --git a/src/lib.cairo b/src/lib.cairo index 6b9d0ec4..88b0ba83 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,6 +1,6 @@ mod airdrop; -mod amm_types { - mod basic; +mod treasury_types { + mod carmine; } mod constants; mod contract; diff --git a/src/options.cairo b/src/options.cairo deleted file mode 100644 index 86d2b84b..00000000 --- a/src/options.cairo +++ /dev/null @@ -1,264 +0,0 @@ -// Handles adding new options to the AMM and linking them to the liquidity pool. -// I have chosen this perhaps rather complex type layout in expectation of generating the options soon – -// – first generating FutureOption, then generating everything from Pragma data - -mod Options { - use konoha::contract::IGovernance; - use traits::{Into, TryInto}; - use array::{ArrayTrait, SpanTrait}; - use option::OptionTrait; - - use starknet::SyscallResultTrait; - use starknet::SyscallResult; - use starknet::class_hash; - use starknet::ClassHash; - use starknet::contract_address::{ - ContractAddress, Felt252TryIntoContractAddress, ContractAddressIntoFelt252 - }; - use starknet::syscalls::deploy_syscall; - use starknet::info::get_contract_address; - - use cubit::f128::types::{Fixed, FixedTrait}; - - use konoha::contract::konoha::{amm_address, proposal_initializer_run}; - use konoha::constants::{ - OPTION_CALL, OPTION_PUT, TRADE_SIDE_LONG, TRADE_SIDE_SHORT, OPTION_TOKEN_CLASS_HASH - }; - use konoha::traits::{ - IAMMDispatcher, IAMMDispatcherTrait, IOptionTokenDispatcher, IOptionTokenDispatcherTrait - }; - use konoha::types::OptionSide; - use konoha::contract::Governance; - use konoha::types::OptionType; - use konoha::contract::konoha::proposal_initializer_runContractMemberStateTrait; - - fn add_options(mut options: Span<FutureOption>) { - // TODO use block hash from block_hash syscall as salt // actually doable with the new syscall - let governance_address = get_contract_address(); - let state = konoha::unsafe_new_contract_state(); - let amm_address = state.get_amm_address(); - loop { - match options.pop_front() { - Option::Some(option) => { add_option(governance_address, amm_address, option); }, - Option::None(()) => { break (); }, - }; - } - } - - // TODO add auto generation of FutureOption structs once string contacenation exists - #[derive(Copy, Drop, Serde)] - struct FutureOption { - name_long: felt252, - name_short: felt252, - maturity: felt252, - strike_price: Fixed, - option_type: OptionType, - lptoken_address: ContractAddress, - btc: bool, - initial_volatility: Fixed - } - - fn add_option( - governance_address: ContractAddress, amm_address: ContractAddress, option: @FutureOption - ) { - let o = *option; - - // mainnet - let USDC_addr: felt252 = 0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8; - let ETH_addr: felt252 = 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7; - let BTC_addr: felt252 = 0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac; - let quote_token_address = USDC_addr; - let base_token_address = if (o.btc) { - BTC_addr - } else { - ETH_addr - }; - - // Yes, this 'overflows', but it's expected and wanted. - let custom_salt: felt252 = 42 - + o.strike_price.mag.into() - + o.maturity - + o.option_type - + o.lptoken_address.into(); - - let opt_class_hash: ClassHash = OPTION_TOKEN_CLASS_HASH.try_into().unwrap(); - let mut optoken_long_calldata = array![]; - optoken_long_calldata.append(o.name_long); - optoken_long_calldata.append('C-OPT'); - optoken_long_calldata.append(amm_address.into()); - optoken_long_calldata.append(quote_token_address); - optoken_long_calldata.append(base_token_address); - optoken_long_calldata.append(o.option_type); - optoken_long_calldata.append(o.strike_price.mag.into()); - optoken_long_calldata.append(o.maturity); - optoken_long_calldata.append(TRADE_SIDE_LONG); - let deploy_retval = deploy_syscall( - opt_class_hash, custom_salt + 1, optoken_long_calldata.span(), false - ); - let (optoken_long_addr, _) = deploy_retval.unwrap_syscall(); - - let mut optoken_short_calldata = array![]; - optoken_short_calldata.append(o.name_short); - optoken_short_calldata.append('C-OPT'); - optoken_short_calldata.append(amm_address.into()); - optoken_short_calldata.append(quote_token_address); - optoken_short_calldata.append(base_token_address); - optoken_short_calldata.append(o.option_type); - optoken_short_calldata.append(o.strike_price.mag.into()); - optoken_short_calldata.append(o.maturity); - optoken_short_calldata.append(TRADE_SIDE_SHORT); - let deploy_retval = deploy_syscall( - opt_class_hash, custom_salt + 2, optoken_short_calldata.span(), false - ); - let (optoken_short_addr, _) = deploy_retval.unwrap_syscall(); - - IAMMDispatcher { contract_address: amm_address } - .add_option_both_sides( - o.maturity.try_into().unwrap(), - o.strike_price, - quote_token_address.try_into().unwrap(), - base_token_address.try_into().unwrap(), - o.option_type, - o.lptoken_address, - optoken_long_addr, - optoken_short_addr, - o.initial_volatility - ); - } - - - fn add_1201_options( - eth_lpt_addr: ContractAddress, - eth_usdc_lpt_addr: ContractAddress, - btc_lpt_addr: ContractAddress, - btc_usdc_lpt_addr: ContractAddress - ) { - let MATURITY: felt252 = 1705017599; - - let point_five = FixedTrait::ONE() / FixedTrait::from_unscaled_felt(2); - - let mut to_add = ArrayTrait::<FutureOption>::new(); - to_add - .append( - FutureOption { - name_long: 'ETHUSDC-12JAN24-2300-LONG-CALL', - name_short: 'ETHUSDC-12JAN24-2300-SHORT-CALL', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(2300), - option_type: OPTION_CALL, - lptoken_address: eth_lpt_addr, - btc: false, - initial_volatility: FixedTrait::from_unscaled_felt(62) - } - ); - to_add - .append( - FutureOption { - name_long: 'ETHUSDC-12JAN24-2400-LONG-CALL', - name_short: 'ETHUSDC-12JAN24-2400-SHORT-CALL', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(2400), - option_type: OPTION_CALL, - lptoken_address: eth_lpt_addr, - btc: false, - initial_volatility: FixedTrait::from_unscaled_felt(62) + point_five - } - ); - to_add - .append( - FutureOption { - name_long: 'ETHUSDC-12JAN24-2500-LONG-CALL', - name_short: 'ETHUSDC-12JAN24-2500-SHORT-CALL', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(2500), - option_type: OPTION_CALL, - lptoken_address: eth_lpt_addr, - btc: false, - initial_volatility: FixedTrait::from_unscaled_felt(64) - } - ); - to_add - .append( - FutureOption { - name_long: 'ETHUSDC-12JAN24-2300-LONG-PUT', - name_short: 'ETHUSDC-12JAN24-2300-SHORT-PUT', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(2300), - option_type: OPTION_PUT, - lptoken_address: eth_usdc_lpt_addr, - btc: false, - initial_volatility: FixedTrait::from_unscaled_felt(62) - } - ); - to_add - .append( - FutureOption { - name_long: 'ETHUSDC-12JAN24-2200-LONG-PUT', - name_short: 'ETHUSDC-12JAN24-2200-SHORT-PUT', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(2200), - option_type: OPTION_PUT, - lptoken_address: eth_usdc_lpt_addr, - btc: false, - initial_volatility: FixedTrait::from_unscaled_felt(62) - } - ); - - // BITCOIN - - to_add - .append( - FutureOption { - name_long: 'BTCUSD-12JAN24-44000-LONG-CALL', - name_short: 'BTCUSD-12JAN24-44000-SHORT-CALL', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(44000), - option_type: OPTION_CALL, - lptoken_address: btc_lpt_addr, - btc: true, - initial_volatility: FixedTrait::from_unscaled_felt(62) + point_five - } - ); - to_add - .append( - FutureOption { - name_long: 'BTCUSD-12JAN24-45000-LONG-CALL', - name_short: 'BTCUSD-12JAN24-45000-SHORT-CALL', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(45000), - option_type: OPTION_CALL, - lptoken_address: btc_lpt_addr, - btc: true, - initial_volatility: FixedTrait::from_unscaled_felt(63) + point_five - } - ); - to_add - .append( - FutureOption { - name_long: 'BTCUSD-12JAN24-43000-LONG-PUT', - name_short: 'BTCUSD-12JAN24-43000-SHORT-PUT', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(43000), - option_type: OPTION_PUT, - lptoken_address: btc_usdc_lpt_addr, - btc: true, - initial_volatility: FixedTrait::from_unscaled_felt(62) - } - ); - to_add - .append( - FutureOption { - name_long: 'BTCUSD-12JAN24-42000-LONG-PUT', - name_short: 'BTCUSD-12JAN24-42000-SHORT-PUT', - maturity: MATURITY, - strike_price: FixedTrait::from_unscaled_felt(42000), - option_type: OPTION_PUT, - lptoken_address: btc_usdc_lpt_addr, - btc: true, - initial_volatility: FixedTrait::from_unscaled_felt(62) - } - ); - - add_options(to_add.span()) - } -} diff --git a/src/proposals.cairo b/src/proposals.cairo index 7f3c294c..689f7ca5 100644 --- a/src/proposals.cairo +++ b/src/proposals.cairo @@ -102,7 +102,8 @@ mod proposals { } fn assert_correct_contract_type(contract_type: ContractType) { - assert(contract_type <= 6, 'invalid contract type') + assert(contract_type != 0 && contract_type != 2, 'unsupported, use custom props'); + assert(contract_type <= 6, 'invalid contract type'); } fn hashing( @@ -449,9 +450,9 @@ mod proposals { let caller_balance_u256: u256 = IERC20Dispatcher { contract_address: gov_token_addr } .balanceOf(caller_addr); - assert(caller_balance_u256.high == 0, 'CARM balance > u128'); + assert(caller_balance_u256.high == 0, 'voting token balance > u128'); let caller_balance: u128 = caller_balance_u256.low; - assert(caller_balance != 0, 'CARM balance is zero'); + assert(caller_balance != 0, 'voting token balance is zero'); let caller_voting_power = caller_balance + self.total_delegated_to.read(caller_addr); diff --git a/src/testing/setup.cairo b/src/testing/setup.cairo index 7e8507b7..e439e88d 100644 --- a/src/testing/setup.cairo +++ b/src/testing/setup.cairo @@ -7,6 +7,7 @@ use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTr use snforge_std::{ BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget }; +use core::ResultTrait; use konoha::contract::IGovernanceDispatcher; @@ -27,10 +28,10 @@ const second_address: felt252 = 0x2; const admin_addr: felt252 = 0x3; fn deploy_governance(token_address: ContractAddress) -> IGovernanceDispatcher { - let gov_contract = declare("Governance"); - let mut args = ArrayTrait::new(); + let gov_contract = declare("Governance").expect('unable to declare governance'); + let mut args: Array<felt252> = ArrayTrait::new(); args.append(token_address.into()); - let address = gov_contract.deploy(@args).expect('unable to deploy governance'); + let (address, _) = gov_contract.deploy(@args).expect('unable to deploy governance'); IGovernanceDispatcher { contract_address: address } } @@ -40,8 +41,10 @@ fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) -> IERC20Dispatc calldata.append(GOV_TOKEN_INITIAL_SUPPLY); calldata.append(recipient.into()); - let gov_token_contract = declare("FloatingToken"); - let token_addr = gov_token_contract.deploy(@calldata).expect('unable to deploy FloatingToken'); + let gov_token_contract = declare("FloatingToken").expect('unable to declare FloatingToken'); + let (token_addr, _) = gov_token_contract + .deploy(@calldata) + .expect('unable to deploy FloatingToken'); let token: IERC20Dispatcher = IERC20Dispatcher { contract_address: token_addr }; start_prank(CheatTarget::One(token_addr), admin_addr.try_into().unwrap()); diff --git a/src/traits.cairo b/src/traits.cairo index cece8097..4d3798ff 100644 --- a/src/traits.cairo +++ b/src/traits.cairo @@ -1,10 +1,6 @@ use starknet::{ClassHash, ContractAddress}; - -use konoha::types::OptionSide; -use konoha::types::OptionType; - use core::starknet::SyscallResultTrait; -use cubit::f128::types::{Fixed, FixedTrait}; + #[starknet::interface] trait IProvidesAddresses<TContractState> { @@ -42,217 +38,6 @@ trait IERC20<TContractState> { fn approve(ref self: TContractState, spender: ContractAddress, amount: u256) -> bool; } -#[starknet::interface] -trait IAMM<TContractState> { - fn trade_open( - ref self: TContractState, - option_type: OptionType, - strike_price: Fixed, - maturity: u64, - option_side: OptionSide, - option_size: u128, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - limit_total_premia: Fixed, - tx_deadline: u64, - ) -> Fixed; - fn trade_close( - ref self: TContractState, - option_type: OptionType, - strike_price: Fixed, - maturity: u64, - option_side: OptionSide, - option_size: u128, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - limit_total_premia: Fixed, - tx_deadline: u64, - ) -> Fixed; - fn trade_settle( - ref self: TContractState, - option_type: OptionType, - strike_price: Fixed, - maturity: u64, - option_side: OptionSide, - option_size: u128, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - ); - fn is_option_available( - self: @TContractState, - lptoken_address: ContractAddress, - option_side: OptionSide, - strike_price: Fixed, - maturity: u64, - ) -> bool; - fn set_trading_halt(ref self: TContractState, new_status: bool); - fn get_trading_halt(self: @TContractState) -> bool; - fn set_trading_halt_permission( - ref self: TContractState, address: ContractAddress, permission: bool - ); - fn get_trading_halt_permission(self: @TContractState, address: ContractAddress) -> bool; - fn add_lptoken( - ref self: TContractState, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - option_type: OptionType, - lptoken_address: ContractAddress, - volatility_adjustment_speed: Fixed, - max_lpool_bal: u256, - ); - fn add_option_both_sides( - ref self: TContractState, - maturity: u64, - strike_price: Fixed, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - option_type: OptionType, - lptoken_address: ContractAddress, - option_token_address_long: ContractAddress, - option_token_address_short: ContractAddress, - initial_volatility: Fixed - ); - - fn get_option_token_address( - self: @TContractState, - lptoken_address: ContractAddress, - option_side: OptionSide, - maturity: u64, - strike_price: Fixed, - ) -> ContractAddress; - fn get_lptokens_for_underlying( - self: @TContractState, pooled_token_addr: ContractAddress, underlying_amt: u256, - ) -> u256; - fn get_underlying_for_lptokens( - self: @TContractState, lptoken_addr: ContractAddress, lpt_amt: u256 - ) -> u256; - fn get_available_lptoken_addresses(self: @TContractState, order_i: felt252) -> ContractAddress; - // fn get_all_options(self: @TContractState, lptoken_address: ContractAddress) -> Array<Option_>; - // fn get_all_non_expired_options_with_premia( - // self: @TContractState, lptoken_address: ContractAddress - // ) -> Array<OptionWithPremia>; - // fn get_option_with_position_of_user( - // self: @TContractState, user_address: ContractAddress - // ) -> Array<OptionWithUsersPosition>; - fn get_all_lptoken_addresses(self: @TContractState,) -> Array<ContractAddress>; - fn get_value_of_pool_position(self: @TContractState, lptoken_address: ContractAddress) -> Fixed; - - fn get_value_of_pool_expired_position( - self: @TContractState, lptoken_address: ContractAddress - ) -> Fixed; - fn get_value_of_pool_non_expired_position( - self: @TContractState, lptoken_address: ContractAddress - ) -> Fixed; - - - // fn get_value_of_position( - // self: @TContractState, - // option: Option_, - // position_size: u128, - // option_type: OptionType, - // current_volatility: Fixed, - // ) -> Fixed; - // fn get_all_poolinfo(self: @TContractState) -> Array<PoolInfo>; - // fn get_user_pool_infos(self: @TContractState, user: ContractAddress) -> Array<UserPoolInfo>; - fn deposit_liquidity( - ref self: TContractState, - pooled_token_addr: ContractAddress, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - option_type: OptionType, - amount: u256, - ); - fn withdraw_liquidity( - ref self: TContractState, - pooled_token_addr: ContractAddress, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - option_type: OptionType, - lp_token_amount: u256, - ); - fn get_unlocked_capital(self: @TContractState, lptoken_address: ContractAddress) -> u256; - fn expire_option_token_for_pool( - ref self: TContractState, - lptoken_address: ContractAddress, - option_side: OptionSide, - strike_price: Fixed, - maturity: u64, - ); - fn set_max_option_size_percent_of_voladjspd( - ref self: TContractState, max_opt_size_as_perc_of_vol_adjspd: u128 - ); - fn get_max_option_size_percent_of_voladjspd(self: @TContractState) -> u128; - fn get_lpool_balance(self: @TContractState, lptoken_address: ContractAddress) -> u256; - fn get_max_lpool_balance(self: @TContractState, lpt_addr: ContractAddress) -> u256; - fn set_max_lpool_balance( - ref self: TContractState, lpt_addr: ContractAddress, max_lpool_bal: u256 - ); - fn get_pool_locked_capital(self: @TContractState, lptoken_address: ContractAddress) -> u256; - // fn get_available_options( - // self: @TContractState, lptoken_address: ContractAddress, order_i: u32 - // ) -> Option_; - - fn get_lptoken_address_for_given_option( - self: @TContractState, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - option_type: OptionType, - ) -> ContractAddress; - // fn get_pool_definition_from_lptoken_address( - // self: @TContractState, lptoken_addres: ContractAddress - // ) -> Pool; - fn get_option_volatility( - self: @TContractState, lptoken_address: ContractAddress, maturity: u64, strike_price: Fixed, - ) -> Fixed; - fn get_underlying_token_address( - self: @TContractState, lptoken_address: ContractAddress - ) -> ContractAddress; - fn get_available_lptoken_addresses_usable_index( - self: @TContractState, starting_index: felt252 - ) -> felt252; - fn get_pool_volatility_adjustment_speed( - self: @TContractState, lptoken_address: ContractAddress - ) -> Fixed; - fn set_pool_volatility_adjustment_speed( - ref self: TContractState, lptoken_address: ContractAddress, new_speed: Fixed - ); - fn get_option_position( - self: @TContractState, - lptoken_address: ContractAddress, - option_side: OptionSide, - maturity: u64, - strike_price: Fixed - ) -> u128; - // fn get_total_premia( - // self: @TContractState, option: Option_, position_size: u256, is_closing: bool - // ) -> (Fixed, Fixed); - - fn black_scholes( - self: @TContractState, - sigma: Fixed, - time_till_maturity_annualized: Fixed, - strike_price: Fixed, - underlying_price: Fixed, - risk_free_rate_annualized: Fixed, - is_for_trade: bool, // bool - ) -> (Fixed, Fixed, bool); - fn get_current_price( - self: @TContractState, - quote_token_address: ContractAddress, - base_token_address: ContractAddress - ) -> Fixed; - fn get_terminal_price( - self: @TContractState, - quote_token_address: ContractAddress, - base_token_address: ContractAddress, - maturity: u64 - ) -> Fixed; - - fn set_pragma_checkpoint(ref self: TContractState, key: felt252); - fn set_pragma_required_checkpoints(ref self: TContractState); - fn upgrade(ref self: TContractState, new_implementation: ClassHash); -} - #[starknet::interface] trait IGovernanceToken<TContractState> { fn name(self: @TContractState) -> felt252; @@ -278,58 +63,3 @@ trait IGovernanceToken<TContractState> { proxy_admin: ContractAddress ); } - -#[starknet::interface] -trait IOptionToken<TState> { - // IERC20 - fn total_supply(self: @TState) -> u256; - fn balance_of(self: @TState, account: ContractAddress) -> u256; - fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256; - fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool; - fn transfer_from( - ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 - ) -> bool; - fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool; - - // IERC20Metadata - fn name(self: @TState) -> felt252; - fn symbol(self: @TState) -> felt252; - fn decimals(self: @TState) -> u8; - - // IERC20SafeAllowance - fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool; - fn decrease_allowance( - ref self: TState, spender: ContractAddress, subtracted_value: u256 - ) -> bool; - - // IERC20CamelOnly - fn totalSupply(self: @TState) -> u256; - fn balanceOf(self: @TState, account: ContractAddress) -> u256; - fn transferFrom( - ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 - ) -> bool; - - // IERC20CamelSafeAllowance - fn increaseAllowance(ref self: TState, spender: ContractAddress, addedValue: u256) -> bool; - fn decreaseAllowance(ref self: TState, spender: ContractAddress, subtractedValue: u256) -> bool; - - // Custom Functions - fn mint(ref self: TState, recipient: ContractAddress, amount: u256); - fn burn(ref self: TState, account: ContractAddress, amount: u256); - fn upgrade(ref self: TState, new_class_hash: ClassHash); - - // Ownable Functions - fn transferOwnership(ref self: TState, newOwner: ContractAddress); - fn renounceOwnership(ref self: TState); - fn owner(self: @TState) -> ContractAddress; - fn transfer_ownership(ref self: TState, new_owner: ContractAddress); - fn renounce_ownership(ref self: TState); - - // Option data - fn quote_token_address(self: @TState) -> ContractAddress; - fn base_token_address(self: @TState) -> ContractAddress; - fn option_type(self: @TState) -> u8; - fn strike_price(self: @TState) -> Fixed; - fn maturity(self: @TState) -> u64; - fn side(self: @TState) -> u8; -} diff --git a/src/treasury.cairo b/src/treasury.cairo index 46e28a3b..49d120ad 100644 --- a/src/treasury.cairo +++ b/src/treasury.cairo @@ -1,5 +1,5 @@ use starknet::ContractAddress; -use konoha::types::OptionType; +use konoha::treasury_types::carmine::OptionType; #[starknet::interface] trait ITreasury<TContractState> { @@ -40,9 +40,8 @@ mod Treasury { use openzeppelin::upgrades::interface::IUpgradeable; use starknet::{ContractAddress, get_caller_address, get_contract_address, ClassHash}; use konoha::airdrop::{IAirdropDispatcher, IAirdropDispatcherTrait}; - use konoha::traits::{ - IERC20Dispatcher, IERC20DispatcherTrait, IAMMDispatcher, IAMMDispatcherTrait - }; + use konoha::traits::{IERC20Dispatcher, IERC20DispatcherTrait}; + use konoha::treasury_types::carmine::{IAMMDispatcher, IAMMDispatcherTrait}; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); diff --git a/src/treasury_types/carmine.cairo b/src/treasury_types/carmine.cairo new file mode 100644 index 00000000..8b3c7fd0 --- /dev/null +++ b/src/treasury_types/carmine.cairo @@ -0,0 +1,62 @@ +use starknet::{ContractAddress, ClassHash}; + +pub type OptionSide = felt252; +pub type OptionType = felt252; + +#[starknet::interface] +pub trait IAMM<TContractState> { + fn get_lptokens_for_underlying( + self: @TContractState, pooled_token_addr: ContractAddress, underlying_amt: u256, + ) -> u256; + fn get_underlying_for_lptokens( + self: @TContractState, lptoken_addr: ContractAddress, lpt_amt: u256 + ) -> u256; + fn get_available_lptoken_addresses(self: @TContractState, order_i: felt252) -> ContractAddress; + fn deposit_liquidity( + ref self: TContractState, + pooled_token_addr: ContractAddress, + quote_token_address: ContractAddress, + base_token_address: ContractAddress, + option_type: OptionType, + amount: u256, + ); + fn withdraw_liquidity( + ref self: TContractState, + pooled_token_addr: ContractAddress, + quote_token_address: ContractAddress, + base_token_address: ContractAddress, + option_type: OptionType, + lp_token_amount: u256, + ); + fn get_unlocked_capital(self: @TContractState, lptoken_address: ContractAddress) -> u256; + fn set_max_option_size_percent_of_voladjspd( + ref self: TContractState, max_opt_size_as_perc_of_vol_adjspd: u128 + ); + fn get_max_option_size_percent_of_voladjspd(self: @TContractState) -> u128; + fn get_lpool_balance(self: @TContractState, lptoken_address: ContractAddress) -> u256; + fn get_max_lpool_balance(self: @TContractState, lpt_addr: ContractAddress) -> u256; + fn set_max_lpool_balance( + ref self: TContractState, lpt_addr: ContractAddress, max_lpool_bal: u256 + ); + fn get_pool_locked_capital(self: @TContractState, lptoken_address: ContractAddress) -> u256; + // fn get_available_options( + // self: @TContractState, lptoken_address: ContractAddress, order_i: u32 + // ) -> Option_; + + fn get_lptoken_address_for_given_option( + self: @TContractState, + quote_token_address: ContractAddress, + base_token_address: ContractAddress, + option_type: OptionType, + ) -> ContractAddress; + // fn get_pool_definition_from_lptoken_address( + // self: @TContractState, lptoken_addres: ContractAddress + // ) -> Pool; + // fn get_total_premia( + // self: @TContractState, option: Option_, position_size: u256, is_closing: bool + // ) -> (Fixed, Fixed); + + fn set_pragma_checkpoint(ref self: TContractState, key: felt252); + fn set_pragma_required_checkpoints(ref self: TContractState); + fn upgrade(ref self: TContractState, new_implementation: ClassHash); +} diff --git a/src/types.cairo b/src/types.cairo index df232ee6..a4e28bdb 100644 --- a/src/types.cairo +++ b/src/types.cairo @@ -18,8 +18,6 @@ type BlockNumber = felt252; type VoteStatus = felt252; // 0 = not voted, 1 = yay, 2 = nay type ContractType = u64; // for Carmine 0 = amm, 1 = governance, 2 = CARM token, 3 = merkle tree root, 4 = no-op/signal vote, 5 = custom proposal -type OptionSide = felt252; -type OptionType = felt252; #[derive(Copy, Drop, Serde, starknet::Store)] struct CustomProposalConfig { diff --git a/src/upgrades.cairo b/src/upgrades.cairo index 5e33f541..32c63a1e 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -26,11 +26,6 @@ mod upgrades { use konoha::proposals::proposals as proposals_component; use konoha::proposals::proposals::ProposalsImpl; use konoha::airdrop::airdrop as airdrop_component; - use konoha::traits::IAMMDispatcher; - use konoha::traits::IAMMDispatcherTrait; - use konoha::traits::IGovernanceTokenDispatcher; - use konoha::traits::IGovernanceTokenDispatcherTrait; - use konoha::traits::get_amm_address_self; use konoha::traits::get_governance_token_address_self; #[storage] @@ -79,20 +74,14 @@ mod upgrades { // Apply the upgrade match contract_type { 0 => { - let amm_addr: ContractAddress = get_amm_address_self(); - IAMMDispatcher { contract_address: amm_addr } - .upgrade(impl_hash.try_into().unwrap()); + panic!("Carmine Options AMM upgrade not supported, use generic proposals"); }, 1 => { let impl_hash_classhash: ClassHash = impl_hash.try_into().unwrap(); let res = syscalls::replace_class_syscall(impl_hash_classhash); res.expect('upgrade failed'); }, - 2 => { - let govtoken_addr = get_governance_token_address_self(); - IGovernanceTokenDispatcher { contract_address: govtoken_addr } - .upgrade(impl_hash); - }, + 2 => { panic!("CARM upgrade not supported, use generic proposals"); }, 3 => { let mut airdrop_comp = get_dep_component_mut!(ref self, Airdrop); airdrop_comp.merkle_root.write(impl_hash); diff --git a/tests/add_options.cairo b/tests/add_options.cairo deleted file mode 100644 index 7dd985a8..00000000 --- a/tests/add_options.cairo +++ /dev/null @@ -1,71 +0,0 @@ -use super::basic::submit_44_signal_proposals; - -use konoha::traits::IAMM; -use konoha::contract::IGovernanceDispatcher; -use konoha::contract::IGovernanceDispatcherTrait; -use konoha::traits::{IAMMDispatcher, IAMMDispatcherTrait, IERC20Dispatcher, IERC20DispatcherTrait}; - -use starknet::{ContractAddress, get_block_timestamp}; - -use snforge_std::{declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget}; -use cubit::f128::types::{Fixed, FixedTrait}; - -use debug::PrintTrait; - -// #[test] -// #[fork("MAINNET")] -// fn test_add_options() { -// submit_44_signal_proposals(); -// let gov_contract_addr: ContractAddress = -// 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f -// .try_into() -// .unwrap(); -// let dispatcher = IGovernanceDispatcher { contract_address: gov_contract_addr }; -// let marek_address: ContractAddress = -// 0x0011d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233 -// .try_into() -// .unwrap(); -// let new_contract: ContractClass = declare('Governance'); -// start_prank(CheatTarget::One(gov_contract_addr), marek_address); -// let ret = dispatcher.submit_proposal(new_contract.class_hash.into(), 1); -// dispatcher.vote(ret, 1); -// let curr_timestamp = get_block_timestamp(); -// let warped_timestamp = curr_timestamp + consteval_int!(60 * 60 * 24 * 7) + 420; -// start_warp(CheatTarget::One(gov_contract_addr), warped_timestamp); -// let status = dispatcher.get_proposal_status(ret); -// dispatcher.apply_passed_proposal(ret); -// dispatcher.add_0501_options(); -// let amm_addr = 0x076dbabc4293db346b0a56b29b6ea9fe18e93742c73f12348c8747ecfc1050aa -// .try_into() -// .unwrap(); -// trade_option(1704412799, marek_address, amm_addr, FixedTrait::from_unscaled_felt(2200)); -// } - -// buys 0.01 long eth/usdc call -fn trade_option( - maturity: u64, trader: ContractAddress, amm_addr: ContractAddress, strike_price: Fixed -) { - let amm = IAMMDispatcher { contract_address: amm_addr }; - start_prank(CheatTarget::One(amm_addr), trader); - let amt = 184467440737095520; - let USDC_addr: felt252 = 0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8; - let ETH_addr: felt252 = 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7; - let quote_token_address = USDC_addr.try_into().unwrap(); - let base_token_address = ETH_addr.try_into().unwrap(); - let curr_timestamp = get_block_timestamp(); - let eth = IERC20Dispatcher { contract_address: base_token_address }; - start_prank(CheatTarget::One(base_token_address), trader); - eth.approve(amm_addr, amt + amt); - amm - .trade_open( - 0, - strike_price, - maturity.into(), - 0, - amt.low.into(), - quote_token_address, - base_token_address, - FixedTrait::ONE(), - (curr_timestamp + 420).into() - ); -} diff --git a/tests/basic.cairo b/tests/basic.cairo index a6eb631c..0880888c 100644 --- a/tests/basic.cairo +++ b/tests/basic.cairo @@ -108,7 +108,7 @@ fn test_upgrade_mainnet_to_master() { top_carm_holders.append(eighth_address); // declare current and submit proposal - let new_contract: ContractClass = declare("Governance"); + let new_contract: ContractClass = declare("Governance").expect('unable to declare governance'); start_prank(CheatTarget::One(gov_contract_addr), scaling_address); let new_prop_id = dispatcher.submit_proposal(new_contract.class_hash.into(), 1); loop { diff --git a/tests/lib.cairo b/tests/lib.cairo index 12bc39ff..5cd13f69 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -1,4 +1,3 @@ -mod add_options; mod basic; mod test_treasury; mod proposals_tests; diff --git a/tests/test_treasury.cairo b/tests/test_treasury.cairo index 4e306ae7..4887ca09 100644 --- a/tests/test_treasury.cairo +++ b/tests/test_treasury.cairo @@ -13,7 +13,6 @@ use core::serde::Serde; use core::option::OptionTrait; use core::traits::{TryInto, Into}; use core::byte_array::ByteArray; -use cubit::f128::types::{Fixed, FixedTrait}; use array::ArrayTrait; use debug::PrintTrait; use starknet::ContractAddress; @@ -22,7 +21,8 @@ use snforge_std::{ stop_roll, }; use konoha::treasury::{ITreasuryDispatcher, ITreasuryDispatcherTrait}; -use konoha::traits::{IERC20Dispatcher, IERC20DispatcherTrait, IAMMDispatcher, IAMMDispatcherTrait}; +use konoha::treasury_types::carmine::{IAMMDispatcher, IAMMDispatcherTrait}; +use konoha::traits::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin::access::ownable::interface::{ IOwnableTwoStep, IOwnableTwoStepDispatcherTrait, IOwnableTwoStepDispatcher }; @@ -35,7 +35,7 @@ fn get_important_addresses() -> (ContractAddress, ContractAddress, ContractAddre let AMM_contract_address: ContractAddress = testStorage::AMM_CONTRACT_ADDRESS .try_into() .unwrap(); - let contract = declare("Treasury"); + let contract = declare("Treasury").expect('unable to declare'); let mut calldata = ArrayTrait::new(); gov_contract_address.serialize(ref calldata); AMM_contract_address.serialize(ref calldata); @@ -44,7 +44,7 @@ fn get_important_addresses() -> (ContractAddress, ContractAddress, ContractAddre let contract_address = contract.precalculate_address(@calldata); prank(CheatTarget::One(contract_address), gov_contract_address, CheatSpan::TargetCalls(1)); - let deployed_contract = contract.deploy(@calldata).unwrap(); + let (deployed_contract, _) = contract.deploy(@calldata).unwrap(); return (gov_contract_address, AMM_contract_address, deployed_contract,); } From eb1181d38b128af849f317c9c7b3a91adfee05f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Thu, 23 May 2024 11:48:52 +0000 Subject: [PATCH 35/39] Rename governance:: to konoha:: --- tests/proposals_tests.cairo | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index fc10d68a..40619d1d 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -7,17 +7,17 @@ use snforge_std::{ BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget }; -use governance::testing::setup::{ +use konoha::testing::setup::{ admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy }; -use governance::contract::IGovernanceDispatcher; -use governance::contract::IGovernanceDispatcherTrait; -use governance::proposals::IProposalsDispatcher; -use governance::proposals::IProposalsDispatcherTrait; -use governance::upgrades::IUpgradesDispatcher; -use governance::upgrades::IUpgradesDispatcherTrait; -use governance::constants; +use konoha::contract::IGovernanceDispatcher; +use konoha::contract::IGovernanceDispatcherTrait; +use konoha::proposals::IProposalsDispatcher; +use konoha::proposals::IProposalsDispatcherTrait; +use konoha::upgrades::IUpgradesDispatcher; +use konoha::upgrades::IUpgradesDispatcherTrait; +use konoha::constants; use starknet::get_block_timestamp; From 9f619800d4cb4edaeda0fe8cf2561e15884dee5d Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Thu, 23 May 2024 18:17:50 +0000 Subject: [PATCH 36/39] Fix proposals tests and mint tokens to admin addr before distributing them in deploy token function --- src/testing/setup.cairo | 2 ++ tests/proposals_tests.cairo | 25 +++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/testing/setup.cairo b/src/testing/setup.cairo index e439e88d..cf96ed7c 100644 --- a/src/testing/setup.cairo +++ b/src/testing/setup.cairo @@ -49,6 +49,8 @@ fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) -> IERC20Dispatc start_prank(CheatTarget::One(token_addr), admin_addr.try_into().unwrap()); + token.mint(admin_addr.try_into().unwrap(), GOV_TOKEN_INITIAL_SUPPLY); + token.transfer(first_address.try_into().unwrap(), 100000); token.transfer(second_address.try_into().unwrap(), 100000); token diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index 40619d1d..d3e5446a 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -7,17 +7,16 @@ use snforge_std::{ BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget }; -use konoha::testing::setup::{ - admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, - test_vote_upgrade_root, check_if_healthy +use governance::testing::setup::{ + admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy }; -use konoha::contract::IGovernanceDispatcher; -use konoha::contract::IGovernanceDispatcherTrait; -use konoha::proposals::IProposalsDispatcher; -use konoha::proposals::IProposalsDispatcherTrait; -use konoha::upgrades::IUpgradesDispatcher; -use konoha::upgrades::IUpgradesDispatcherTrait; -use konoha::constants; +use governance::contract::IGovernanceDispatcher; +use governance::contract::IGovernanceDispatcherTrait; +use governance::proposals::IProposalsDispatcher; +use governance::proposals::IProposalsDispatcherTrait; +use governance::upgrades::IUpgradesDispatcher; +use governance::upgrades::IUpgradesDispatcherTrait; +use governance::constants; use starknet::get_block_timestamp; @@ -40,7 +39,7 @@ fn test_express_proposal() { assert!(dispatcher.get_proposal_status(prop_id) == 1, "proposal not passed!"); } -#[should_panic] +#[test] fn test_proposal_expiry() { let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); let gov_contract = deploy_governance(token_contract.contract_address); @@ -57,9 +56,11 @@ fn test_proposal_expiry() { start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); let status = dispatcher.get_proposal_status(prop_id); + assert!(dispatcher.get_proposal_status(prop_id) == constants::MINUS_ONE, "proposal not expired!"); } -#[should_panic] +#[test] +#[should_panic(expected: ('Cannot vote on an expired proposal',))] fn test_vote_on_expired_proposal() { let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); let gov_contract = deploy_governance(token_contract.contract_address); From d837e289c86be864100c612a158ee0ef2aa75a08 Mon Sep 17 00:00:00 2001 From: Nerrolol <nassim.amerouali@gmail.com> Date: Fri, 24 May 2024 18:36:22 +0000 Subject: [PATCH 37/39] Add quorum tests --- tests/proposals_tests.cairo | 56 +++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index d3e5446a..bfd8ddf3 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -7,16 +7,16 @@ use snforge_std::{ BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget }; -use governance::testing::setup::{ +use konoha::testing::setup::{ admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy }; -use governance::contract::IGovernanceDispatcher; -use governance::contract::IGovernanceDispatcherTrait; -use governance::proposals::IProposalsDispatcher; -use governance::proposals::IProposalsDispatcherTrait; -use governance::upgrades::IUpgradesDispatcher; -use governance::upgrades::IUpgradesDispatcherTrait; -use governance::constants; +use konoha::contract::IGovernanceDispatcher; +use konoha::contract::IGovernanceDispatcherTrait; +use konoha::proposals::IProposalsDispatcher; +use konoha::proposals::IProposalsDispatcherTrait; +use konoha::upgrades::IUpgradesDispatcher; +use konoha::upgrades::IUpgradesDispatcherTrait; +use konoha::constants; use starknet::get_block_timestamp; @@ -79,3 +79,43 @@ fn test_vote_on_expired_proposal() { start_prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap()); dispatcher.vote(prop_id, 1); } + +#[test] +fn test_vote_on_quorum_not_met() { + let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); + let gov_contract = deploy_governance(token_contract.contract_address); + let gov_contract_addr = gov_contract.contract_address; + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); + let prop_id = dispatcher.submit_proposal(42, 1); + + start_prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap()); + dispatcher.vote(prop_id, 1); + + let (yay_votes, nay_votes) = dispatcher.get_vote_counts(prop_id); + let total_votes = yay_votes + nay_votes; + let total_eligible_votes: u128 = IERC20Dispatcher { + contract_address: token_contract.contract_address + } + .totalSupply() + .low; + let quorum_threshold = total_eligible_votes * constants::QUORUM / 100; + + assert!(total_votes < quorum_threshold, "Total votes should be less than quorum threshold"); + assert!(dispatcher.get_proposal_status(prop_id) == constants::MINUS_ONE, "Proposal shouldn't pass when quorum not met"); +} + +#[test] +#[should_panic(expected: ('not enough tokens to submit proposal',))] +fn_test_submit_proposal_under_quorum() { + let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); + let gov_contract = deploy_governance(token_contract.contract_address); + let gov_contract_addr = gov_contract.contract_address; + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + + start_prank(CheatTarget::One(gov_contract_addr), first_address); + dispatcher.submit_proposal(42,1); +} \ No newline at end of file From 513560712b911689d7c71a15003853d292d519ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Mon, 27 May 2024 15:55:22 +0000 Subject: [PATCH 38/39] Move setup to testing, fix tests so they compile --- Scarb.toml | 4 +-- src/lib.cairo | 3 --- tests/basic.cairo | 2 +- tests/lib.cairo | 1 + tests/proposals_tests.cairo | 40 +++++++++++++++++++----------- {src/testing => tests}/setup.cairo | 15 +++-------- 6 files changed, 34 insertions(+), 31 deletions(-) rename {src/testing => tests}/setup.cairo (86%) diff --git a/Scarb.toml b/Scarb.toml index 9e596461..c140fded 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -7,11 +7,11 @@ cairo-version = "2.6.3" [dependencies] starknet = ">=2.0.0" openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.10.0" } -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.23.0" } # can be fixed by doing import super::testing from tests -# [dev-dependencies] sadly can't use this because we have testing in src/ +[dev-dependencies] +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.23.0" } [lib] diff --git a/src/lib.cairo b/src/lib.cairo index 88b0ba83..5dc507cf 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -13,6 +13,3 @@ mod treasury; mod types; mod upgrades; mod voting_token; -mod testing { - mod setup; -} diff --git a/tests/basic.cairo b/tests/basic.cairo index 0880888c..c9de1d6d 100644 --- a/tests/basic.cairo +++ b/tests/basic.cairo @@ -21,7 +21,7 @@ fn test_submit_proposal() { let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; // corresponding govtoken: 0x05151bfdd47826df3669033ea7fb977d3b2d45c4f4d1c439a9edf4062bf34bfa // has one holder, with 31 CARM: 0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1 - let admin_addr: ContractAddress = + let _admin_addr: ContractAddress = 0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1 .try_into() .unwrap(); diff --git a/tests/lib.cairo b/tests/lib.cairo index 5cd13f69..8da5582c 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -2,3 +2,4 @@ mod basic; mod test_treasury; mod proposals_tests; mod airdrop_tests; +mod setup; \ No newline at end of file diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index bfd8ddf3..548a8811 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -2,12 +2,12 @@ use array::ArrayTrait; use core::traits::TryInto; use debug::PrintTrait; use starknet::ContractAddress; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait, IERC20CamelOnlyDispatcher, IERC20CamelOnlyDispatcherTrait}; use snforge_std::{ - BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget + BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget, prank, CheatSpan }; -use konoha::testing::setup::{ +use super::setup::{ admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy }; use konoha::contract::IGovernanceDispatcher; @@ -56,11 +56,11 @@ fn test_proposal_expiry() { start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); let status = dispatcher.get_proposal_status(prop_id); - assert!(dispatcher.get_proposal_status(prop_id) == constants::MINUS_ONE, "proposal not expired!"); + assert!(status == constants::MINUS_ONE, "proposal not expired!"); } #[test] -#[should_panic(expected: ('Cannot vote on an expired proposal',))] +#[should_panic(expected: ('voting concluded',))] fn test_vote_on_expired_proposal() { let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); let gov_contract = deploy_governance(token_contract.contract_address); @@ -76,6 +76,9 @@ fn test_vote_on_expired_proposal() { let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); + + prank(CheatTarget::One(token_contract.contract_address), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); + token_contract.transfer(first_address.try_into().unwrap(), 100000.try_into().unwrap()); start_prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap()); dispatcher.vote(prop_id, 1); } @@ -88,34 +91,43 @@ fn test_vote_on_quorum_not_met() { let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); + prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); let prop_id = dispatcher.submit_proposal(42, 1); - start_prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap()); + prank(CheatTarget::One(token_contract.contract_address), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); + token_contract.transfer(first_address.try_into().unwrap(), 100000.try_into().unwrap()); + + prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap(), CheatSpan::TargetCalls(1)); dispatcher.vote(prop_id, 1); let (yay_votes, nay_votes) = dispatcher.get_vote_counts(prop_id); let total_votes = yay_votes + nay_votes; - let total_eligible_votes: u128 = IERC20Dispatcher { + let total_eligible_votes: u128 = IERC20CamelOnlyDispatcher { contract_address: token_contract.contract_address } .totalSupply() .low; let quorum_threshold = total_eligible_votes * constants::QUORUM / 100; - assert!(total_votes < quorum_threshold, "Total votes should be less than quorum threshold"); - assert!(dispatcher.get_proposal_status(prop_id) == constants::MINUS_ONE, "Proposal shouldn't pass when quorum not met"); + assert(total_votes < quorum_threshold, 'Total votes >= quorum threshold'); + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; + start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); + assert(dispatcher.get_proposal_status(prop_id) == constants::MINUS_ONE, 'Proposal pass & quorum not met'); } #[test] -#[should_panic(expected: ('not enough tokens to submit proposal',))] -fn_test_submit_proposal_under_quorum() { +#[should_panic(expected: ('not enough tokens to submit',))] +fn test_submit_proposal_under_quorum() { let token_contract = deploy_and_distribute_gov_tokens(admin_addr.try_into().unwrap()); let gov_contract = deploy_governance(token_contract.contract_address); let gov_contract_addr = gov_contract.contract_address; let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - start_prank(CheatTarget::One(gov_contract_addr), first_address); + prank(CheatTarget::One(token_contract.contract_address), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); + token_contract.transfer(first_address.try_into().unwrap(), 100000.try_into().unwrap()); + + prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap(), CheatSpan::TargetCalls(1)); dispatcher.submit_proposal(42,1); -} \ No newline at end of file +} diff --git a/src/testing/setup.cairo b/tests/setup.cairo similarity index 86% rename from src/testing/setup.cairo rename to tests/setup.cairo index cf96ed7c..f6d09b76 100644 --- a/src/testing/setup.cairo +++ b/tests/setup.cairo @@ -21,7 +21,7 @@ use openzeppelin::token::erc20::interface::IERC20; use starknet::get_block_timestamp; -const GOV_TOKEN_INITIAL_SUPPLY: felt252 = 1000000000000000000; +const GOV_TOKEN_INITIAL_SUPPLY: u256 = 1000000000000000000; const first_address: felt252 = 0x1; const second_address: felt252 = 0x2; @@ -38,22 +38,15 @@ fn deploy_governance(token_address: ContractAddress) -> IGovernanceDispatcher { fn deploy_and_distribute_gov_tokens(recipient: ContractAddress) -> IERC20Dispatcher { let mut calldata = ArrayTrait::new(); - calldata.append(GOV_TOKEN_INITIAL_SUPPLY); + calldata.append(GOV_TOKEN_INITIAL_SUPPLY.low.into()); + calldata.append(GOV_TOKEN_INITIAL_SUPPLY.high.into()); calldata.append(recipient.into()); let gov_token_contract = declare("FloatingToken").expect('unable to declare FloatingToken'); let (token_addr, _) = gov_token_contract .deploy(@calldata) .expect('unable to deploy FloatingToken'); - let token: IERC20Dispatcher = IERC20Dispatcher { contract_address: token_addr }; - - start_prank(CheatTarget::One(token_addr), admin_addr.try_into().unwrap()); - - token.mint(admin_addr.try_into().unwrap(), GOV_TOKEN_INITIAL_SUPPLY); - - token.transfer(first_address.try_into().unwrap(), 100000); - token.transfer(second_address.try_into().unwrap(), 100000); - token + IERC20Dispatcher { contract_address: token_addr } } From 9109ef38d295aa606bea8fbfa87cc4a515b12b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <ondrej.sojka@gmail.com> Date: Mon, 27 May 2024 16:00:26 +0000 Subject: [PATCH 39/39] Merge branch master --- src/contract.cairo | 16 ++++- src/lib.cairo | 1 + src/vesting.cairo | 36 +++++++----- tests/lib.cairo | 2 +- tests/proposals_tests.cairo | 55 +++++++++++++---- tests/test_treasury.cairo | 114 +++++++++++++++++++++++++++++++++--- tests/vesting.cairo | 114 ++++++++++++++++++++++++++++++++++++ 7 files changed, 299 insertions(+), 39 deletions(-) create mode 100644 tests/vesting.cairo diff --git a/src/contract.cairo b/src/contract.cairo index 4c624e78..5be3afee 100644 --- a/src/contract.cairo +++ b/src/contract.cairo @@ -18,6 +18,9 @@ trait IGovernance<TContractState> { // in component +// VESTING + +// in component // OPTIONS / ONE-OFF } @@ -31,17 +34,21 @@ mod Governance { use konoha::proposals::proposals as proposals_component; use konoha::upgrades::upgrades as upgrades_component; use konoha::airdrop::airdrop as airdrop_component; + use konoha::vesting::vesting as vesting_component; use starknet::ContractAddress; component!(path: airdrop_component, storage: airdrop, event: AirdropEvent); + component!(path: vesting_component, storage: vesting, event: VestingEvent); component!(path: proposals_component, storage: proposals, event: ProposalsEvent); component!(path: upgrades_component, storage: upgrades, event: UpgradesEvent); #[abi(embed_v0)] impl Airdrop = airdrop_component::AirdropImpl<ContractState>; + #[abi(embed_v0)] + impl Vesting = vesting_component::VestingImpl<ContractState>; #[abi(embed_v0)] impl Proposals = proposals_component::ProposalsImpl<ContractState>; @@ -53,10 +60,12 @@ mod Governance { proposal_initializer_run: LegacyMap::<u64, bool>, governance_token_address: ContractAddress, #[substorage(v0)] - proposals: proposals_component::Storage, - #[substorage(v0)] airdrop: airdrop_component::Storage, #[substorage(v0)] + vesting: vesting_component::Storage, + #[substorage(v0)] + proposals: proposals_component::Storage, + #[substorage(v0)] upgrades: upgrades_component::Storage } @@ -66,7 +75,7 @@ mod Governance { struct Proposed { prop_id: felt252, payload: felt252, - to_upgrade: ContractType + to_upgrade: ContractType, } #[derive(starknet::Event, Drop)] @@ -82,6 +91,7 @@ mod Governance { Proposed: Proposed, Voted: Voted, AirdropEvent: airdrop_component::Event, + VestingEvent: vesting_component::Event, ProposalsEvent: proposals_component::Event, UpgradesEvent: upgrades_component::Event } diff --git a/src/lib.cairo b/src/lib.cairo index 5dc507cf..9fe8f50e 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -12,4 +12,5 @@ mod traits; mod treasury; mod types; mod upgrades; +mod vesting; mod voting_token; diff --git a/src/vesting.cairo b/src/vesting.cairo index f62087e0..2c42af38 100644 --- a/src/vesting.cairo +++ b/src/vesting.cairo @@ -15,8 +15,9 @@ trait IVesting<TContractState> { ref self: TContractState, first_vest: u64, period: u64, - increments_count: u64, - total_amount: u128 + increments_count: u16, + total_amount: u128, + grantee: ContractAddress ); // MAYBE – streaming? // MAYBE – options on the govtoken? @@ -24,10 +25,11 @@ trait IVesting<TContractState> { #[starknet::component] mod vesting { - use starknet::syscalls::get_block_timestamp; - - use konoha::traits::IGovernanceTokenDispatcher; - use konoha::traits::IGovernanceTokenDispatcherTrait; + use starknet::ContractAddress; + use starknet::{get_block_timestamp, get_caller_address, get_contract_address}; + use konoha::contract::Governance; + use konoha::contract::{IGovernanceDispatcher, IGovernanceDispatcherTrait}; + use konoha::traits::{IGovernanceTokenDispatcher, IGovernanceTokenDispatcherTrait}; #[storage] struct Storage { @@ -65,10 +67,11 @@ mod vesting { vested_timestamp: u64 ) { let amt_to_vest = self.milestone.read((vested_timestamp, grantee)); - assert(amt_to_vest != 0, 'no vesting milestone found, or already vested'); + assert(amt_to_vest != 0, 'nothing to vest'); assert(get_block_timestamp() > vested_timestamp, 'not yet eligible'); - IGovernanceTokenDispatcher { contract_address: govtoken_addr } - .mint(claimee, u256 { high: 0, low: amt_to_vest }); + let self_dsp = IGovernanceDispatcher { contract_address: get_contract_address() }; + IGovernanceTokenDispatcher { contract_address: self_dsp.get_governance_token_address() } + .mint(grantee, amt_to_vest.into()); self.milestone.write((vested_timestamp, grantee), 0); self .emit( @@ -82,29 +85,30 @@ mod vesting { grantee: ContractAddress, amount: u128 ) { - self.milestone.write((vested_timestamp, grantee), amount); + assert(get_caller_address() == get_contract_address(), 'not self-call'); + self.milestone.write((vesting_timestamp, grantee), amount); self .emit( VestingMilestoneAdded { - grantee: grantee, timestamp: vesting_timestamp, amount: u128 + grantee: grantee, timestamp: vesting_timestamp, amount: amount } ) } fn add_linear_vesting_schedule( - ref self: TContractState, + ref self: ComponentState<TContractState>, first_vest: u64, period: u64, increments_count: u16, total_amount: u128, grantee: ContractAddress ) { + assert(get_caller_address() == get_contract_address(), 'not self-call'); let mut i: u16 = 0; let mut curr_timestamp = first_vest; - assert(increments_count > 1, 'schedule must have more than one milestone'); - assert(get_block_timestamp() < first_vest, 'first vest cannot be in the past'); - assert() - let per_vest_amount = total_amount / increments_count; + assert(increments_count > 1, 'increments_count <= 1'); + assert(get_block_timestamp() < first_vest, 'first vest can\'t be in the past'); + let per_vest_amount = total_amount / increments_count.into(); let mut total_scheduled = 0; loop { if i == increments_count { diff --git a/tests/lib.cairo b/tests/lib.cairo index 8da5582c..4feb9077 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -2,4 +2,4 @@ mod basic; mod test_treasury; mod proposals_tests; mod airdrop_tests; -mod setup; \ No newline at end of file +mod setup; diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index 548a8811..80df3d78 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -2,13 +2,18 @@ use array::ArrayTrait; use core::traits::TryInto; use debug::PrintTrait; use starknet::ContractAddress; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait, IERC20CamelOnlyDispatcher, IERC20CamelOnlyDispatcherTrait}; +use openzeppelin::token::erc20::interface::{ + IERC20Dispatcher, IERC20DispatcherTrait, IERC20CamelOnlyDispatcher, + IERC20CamelOnlyDispatcherTrait +}; use snforge_std::{ - BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget, prank, CheatSpan + BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget, + prank, CheatSpan }; use super::setup::{ - admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, test_vote_upgrade_root, check_if_healthy + admin_addr, first_address, second_address, deploy_governance, deploy_and_distribute_gov_tokens, + test_vote_upgrade_root, check_if_healthy }; use konoha::contract::IGovernanceDispatcher; use konoha::contract::IGovernanceDispatcherTrait; @@ -76,8 +81,11 @@ fn test_vote_on_expired_proposal() { let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); - - prank(CheatTarget::One(token_contract.contract_address), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); + prank( + CheatTarget::One(token_contract.contract_address), + admin_addr.try_into().unwrap(), + CheatSpan::TargetCalls(1) + ); token_contract.transfer(first_address.try_into().unwrap(), 100000.try_into().unwrap()); start_prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap()); dispatcher.vote(prop_id, 1); @@ -91,13 +99,25 @@ fn test_vote_on_quorum_not_met() { let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); + prank( + CheatTarget::One(gov_contract_addr), + admin_addr.try_into().unwrap(), + CheatSpan::TargetCalls(1) + ); let prop_id = dispatcher.submit_proposal(42, 1); - prank(CheatTarget::One(token_contract.contract_address), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); + prank( + CheatTarget::One(token_contract.contract_address), + admin_addr.try_into().unwrap(), + CheatSpan::TargetCalls(1) + ); token_contract.transfer(first_address.try_into().unwrap(), 100000.try_into().unwrap()); - prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap(), CheatSpan::TargetCalls(1)); + prank( + CheatTarget::One(gov_contract_addr), + first_address.try_into().unwrap(), + CheatSpan::TargetCalls(1) + ); dispatcher.vote(prop_id, 1); let (yay_votes, nay_votes) = dispatcher.get_vote_counts(prop_id); @@ -113,7 +133,10 @@ fn test_vote_on_quorum_not_met() { let current_timestamp = get_block_timestamp(); let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS; start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1); - assert(dispatcher.get_proposal_status(prop_id) == constants::MINUS_ONE, 'Proposal pass & quorum not met'); + assert( + dispatcher.get_proposal_status(prop_id) == constants::MINUS_ONE, + 'Proposal pass & quorum not met' + ); } #[test] @@ -125,9 +148,17 @@ fn test_submit_proposal_under_quorum() { let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; - prank(CheatTarget::One(token_contract.contract_address), admin_addr.try_into().unwrap(), CheatSpan::TargetCalls(1)); + prank( + CheatTarget::One(token_contract.contract_address), + admin_addr.try_into().unwrap(), + CheatSpan::TargetCalls(1) + ); token_contract.transfer(first_address.try_into().unwrap(), 100000.try_into().unwrap()); - prank(CheatTarget::One(gov_contract_addr), first_address.try_into().unwrap(), CheatSpan::TargetCalls(1)); - dispatcher.submit_proposal(42,1); + prank( + CheatTarget::One(gov_contract_addr), + first_address.try_into().unwrap(), + CheatSpan::TargetCalls(1) + ); + dispatcher.submit_proposal(42, 1); } diff --git a/tests/test_treasury.cairo b/tests/test_treasury.cairo index 4887ca09..aae30046 100644 --- a/tests/test_treasury.cairo +++ b/tests/test_treasury.cairo @@ -4,8 +4,8 @@ mod testStorage { const zero_address: felt252 = 0; const GOV_CONTRACT_ADDRESS: felt252 = 0x0304256e5fade73a6fc8f49ed7c1c43ac34e6867426601b01204e1f7ba05b53d; - const AMM_CONTRACT_ADDRESS: felt252 = - 0x018890b58b08f341acd1292e8f67edfb01f539c835ef4a2176946a995fe794a5; + const CARMINE_AMM_CONTRACT_ADDRESS: felt252 = + 0x047472e6755afc57ada9550b6a3ac93129cc4b5f98f51c73e0644d129fd208d9; } use core::result::ResultTrait; @@ -15,10 +15,9 @@ use core::traits::{TryInto, Into}; use core::byte_array::ByteArray; use array::ArrayTrait; use debug::PrintTrait; -use starknet::ContractAddress; +use starknet::{ContractAddress, get_block_number, ClassHash}; use snforge_std::{ - BlockId, declare, ContractClassTrait, ContractClass, prank, CheatSpan, CheatTarget, start_roll, - stop_roll, + BlockId, declare, ContractClassTrait, ContractClass, prank, CheatSpan, CheatTarget, roll }; use konoha::treasury::{ITreasuryDispatcher, ITreasuryDispatcherTrait}; use konoha::treasury_types::carmine::{IAMMDispatcher, IAMMDispatcherTrait}; @@ -26,13 +25,13 @@ use konoha::traits::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin::access::ownable::interface::{ IOwnableTwoStep, IOwnableTwoStepDispatcherTrait, IOwnableTwoStepDispatcher }; - +use openzeppelin::upgrades::interface::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait}; fn get_important_addresses() -> (ContractAddress, ContractAddress, ContractAddress) { let gov_contract_address: ContractAddress = testStorage::GOV_CONTRACT_ADDRESS .try_into() .unwrap(); - let AMM_contract_address: ContractAddress = testStorage::AMM_CONTRACT_ADDRESS + let AMM_contract_address: ContractAddress = testStorage::CARMINE_AMM_CONTRACT_ADDRESS .try_into() .unwrap(); let contract = declare("Treasury").expect('unable to declare'); @@ -166,3 +165,104 @@ fn test_ownership_transfer() { ); } +#[test] +#[should_panic(expected: ('Caller is not the pending owner',))] +fn test_revoked_ownership_transfer() { + let (gov_contract_address, _AMM_contract_address, treasury_contract_address) = + get_important_addresses(); + let user2: ContractAddress = '0xUser2'.try_into().unwrap(); + + prank( + CheatTarget::One(treasury_contract_address), gov_contract_address, CheatSpan::TargetCalls(1) + ); + IOwnableTwoStepDispatcher { contract_address: treasury_contract_address } + .transfer_ownership(user2); + assert( + IOwnableTwoStepDispatcher { contract_address: treasury_contract_address } + .pending_owner() == user2, + 'Pending transfer failed' + ); + + // governance transfers ownership back to itself + prank( + CheatTarget::One(treasury_contract_address), gov_contract_address, CheatSpan::TargetCalls(1) + ); + IOwnableTwoStepDispatcher { contract_address: treasury_contract_address } + .transfer_ownership(gov_contract_address); + assert( + IOwnableTwoStepDispatcher { contract_address: treasury_contract_address } + .owner() == gov_contract_address, + 'owner transferred but shouldnt' + ); + + // user2 tries to accept but can't + prank(CheatTarget::One(treasury_contract_address), user2, CheatSpan::TargetCalls(1)); + IOwnableTwoStepDispatcher { contract_address: treasury_contract_address }.accept_ownership(); +} + +#[test] +#[fork("MAINNET")] +fn test_deposit_withdraw_carmine() { + let (gov_contract_address, _AMM_contract_address, treasury_contract_address) = + get_important_addresses(); + let eth_addr: ContractAddress = + 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 + .try_into() + .unwrap(); + let sequencer_address: ContractAddress = + 0x01176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8 + .try_into() + .unwrap(); // random whale + + prank(CheatTarget::One(eth_addr), sequencer_address, CheatSpan::TargetCalls(1)); + let transfer_dispatcher = IERC20Dispatcher { contract_address: eth_addr }; + let oneeth = 1000000000000000000; + let to_deposit = 900000000000000000; + transfer_dispatcher.transfer(treasury_contract_address, oneeth); + assert( + transfer_dispatcher.balanceOf(treasury_contract_address) >= to_deposit, 'balance too low??' + ); + prank( + CheatTarget::One(treasury_contract_address), gov_contract_address, CheatSpan::TargetCalls(1) + ); + + transfer_dispatcher.approve(treasury_contract_address, to_deposit); + let treasury_dispatcher = ITreasuryDispatcher { contract_address: treasury_contract_address }; + prank( + CheatTarget::One(treasury_contract_address), gov_contract_address, CheatSpan::TargetCalls(2) + ); + let usdc_addr: ContractAddress = + 0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8 + .try_into() + .unwrap(); + treasury_dispatcher + .provide_liquidity_to_carm_AMM(eth_addr, usdc_addr, eth_addr, 0, to_deposit.into()); + + roll( + CheatTarget::All, get_block_number() + 1, CheatSpan::Indefinite + ); // to bypass sandwich guard + treasury_dispatcher + .withdraw_liquidity( + eth_addr, usdc_addr, eth_addr, 0, (to_deposit - 100000000000000000).into() + ); + assert( + transfer_dispatcher.balanceOf(treasury_contract_address) >= to_deposit, 'balance too low??' + ); +} + +#[test] +fn test_upgrade_treasury_contract() { + let (gov_contract_address, _AMM_contract_address, treasury_contract_address) = + get_important_addresses(); + + let new_class_hash: ClassHash = + 0x03eb5d443f730133de67b82901cd4b038098c814ad21d811baef9cbd5daeafec + .try_into() + .unwrap(); + + // Ensure only the owner (governance) can upgrade the contract + prank( + CheatTarget::One(treasury_contract_address), gov_contract_address, CheatSpan::TargetCalls(1) + ); + IUpgradeableDispatcher { contract_address: treasury_contract_address }.upgrade(new_class_hash); +} diff --git a/tests/vesting.cairo b/tests/vesting.cairo new file mode 100644 index 00000000..d8a243f0 --- /dev/null +++ b/tests/vesting.cairo @@ -0,0 +1,114 @@ +use core::option::OptionTrait; +use core::result::ResultTrait; +use array::ArrayTrait; +use core::traits::TryInto; +use debug::PrintTrait; +use starknet::ContractAddress; +use snforge_std::{ + BlockId, declare, ContractClassTrait, ContractClass, start_prank, start_warp, CheatTarget +}; + +use konoha::vesting::{IVestingDispatcher, IVestingDispatcherTrait, IVesting}; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; + +// returns gov addr, token addr +fn test_setup() -> (ContractAddress, ContractAddress) { + let new_gov_contract: ContractClass = declare("Governance") + .expect('unable to declare Governance'); + let new_token_contract: ContractClass = declare("MyToken").expect('unable to declare MyToken'); + let new_gov_addr: ContractAddress = + 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f + .try_into() + .unwrap(); + let mut token_constructor = ArrayTrait::new(); + token_constructor.append(new_gov_addr.into()); // Owner + let (token_address, _) = new_token_contract + .deploy(@token_constructor) + .expect('unable to deploy token'); + let mut gov_constructor: Array<felt252> = ArrayTrait::new(); + gov_constructor.append(token_address.into()); + let (gov_address, _) = new_gov_contract + .deploy_at(@gov_constructor, new_gov_addr) + .expect('unable to deploy gov'); + + (gov_address, token_address) +} + +#[test] +#[should_panic(expected: ('not self-call',))] +fn test_unauthorized_add_vesting_schedule() { + let (gov_address, _) = test_setup(); + + let gov_vesting = IVestingDispatcher { contract_address: gov_address }; + + start_warp(CheatTarget::All, 1); + + gov_vesting.add_linear_vesting_schedule(10, 10, 10, 1000000, 0x1.try_into().unwrap()); +} + +#[test] +#[should_panic(expected: ('not yet eligible',))] +fn test_unauthorized_vest_early() { + let (gov_address, _) = test_setup(); + + let gov_vesting = IVestingDispatcher { contract_address: gov_address }; + + start_warp(CheatTarget::All, 1); + start_prank(CheatTarget::One(gov_address), gov_address); + + let grantee: ContractAddress = 0x1.try_into().unwrap(); + + gov_vesting.add_linear_vesting_schedule(10, 10, 10, 1000000, grantee); + + gov_vesting.vest(grantee, 10); +} + +#[test] +#[should_panic(expected: ('nothing to vest',))] +fn test_vest_twice() { + let (gov_address, _) = test_setup(); + + let gov_vesting = IVestingDispatcher { contract_address: gov_address }; + + start_warp(CheatTarget::All, 1); + start_prank(CheatTarget::One(gov_address), gov_address); + + let grantee: ContractAddress = 0x1.try_into().unwrap(); + + gov_vesting.add_linear_vesting_schedule(10, 10, 10, 1000000, grantee); + + start_warp(CheatTarget::All, 11); + + gov_vesting.vest(grantee, 10); + gov_vesting.vest(grantee, 10); +} + +#[test] +fn test_add_simple_vesting_schedule() { + let (gov_address, token_address) = test_setup(); + + let gov_vesting = IVestingDispatcher { contract_address: gov_address }; + let tok = IERC20Dispatcher { contract_address: token_address }; + + start_warp(CheatTarget::All, 1); + start_prank(CheatTarget::One(gov_address), gov_address); + + let grantee: ContractAddress = 0x1.try_into().unwrap(); + gov_vesting.add_linear_vesting_schedule(10, 10, 10, 1000001, grantee); + + start_warp(CheatTarget::All, 11); // past first vest + // anyone can claim for the grantee + gov_vesting.vest(grantee, 10); + assert(tok.balance_of(grantee) == 100000, 'vesting unsuccessful'); + + // grantee themselves can claim too + start_prank(CheatTarget::One(gov_address), grantee); + start_warp(CheatTarget::All, 21); // past second vest + gov_vesting.vest(grantee, 20); + assert(tok.balance_of(grantee) == 200000, 'vesting unsuccessful'); + + start_warp(CheatTarget::All, 101); // past last vest. no requirement to vest in order + gov_vesting.vest(grantee, 100); + // leftover tokens are included in last vest. (remainder after division) + assert(tok.balance_of(grantee) == 300001, 'vesting unsuccessful'); +}