From a85007343fc7570af850983d8991b25e72087e50 Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Fri, 5 Jul 2024 18:16:02 +0200 Subject: [PATCH 1/9] contract: add `is_valid` in `IFees` trait --- contracts/ark_oz/src/erc2981/erc2981.cairo | 25 +++++++++------------- contracts/ark_oz/src/erc2981/fees.cairo | 15 ++++++++++--- contracts/ark_oz/tests/test_erc2981.cairo | 15 +++++++++++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/contracts/ark_oz/src/erc2981/erc2981.cairo b/contracts/ark_oz/src/erc2981/erc2981.cairo index f03450a29..7b0c45b3f 100644 --- a/contracts/ark_oz/src/erc2981/erc2981.cairo +++ b/contracts/ark_oz/src/erc2981/erc2981.cairo @@ -40,6 +40,10 @@ pub mod ERC2981Component { receiver: ContractAddress, } + pub mod Errors { + pub const NOT_VALID_FEES_RATIO: felt252 = 'Fees ratio is not valid'; + } + #[embeddable_as(ERC2981Impl)] impl ERC2981< TContractState, +HasComponent @@ -75,16 +79,11 @@ pub mod ERC2981Component { ) { let ownable_component = get_dep_component!(@self, Ownable); ownable_component.assert_only_owner(); + assert(fees_ratio.is_valid(), Errors::NOT_VALID_FEES_RATIO); self.default_receiver.write(receiver); - let new_fees_ratio = if fees_ratio.denominator.is_zero() { - Default::default() - } else { - fees_ratio - }; - - self.default_fees.write(new_fees_ratio); - self.emit(DefaultRoyaltyUpdated { fees_ratio: new_fees_ratio, receiver: receiver, }); + self.default_fees.write(fees_ratio); + self.emit(DefaultRoyaltyUpdated { fees_ratio: fees_ratio, receiver: receiver, }); } fn token_royalty( @@ -106,19 +105,15 @@ pub mod ERC2981Component { ) { let ownable_component = get_dep_component!(@self, Ownable); ownable_component.assert_only_owner(); + assert(fees_ratio.is_valid(), Errors::NOT_VALID_FEES_RATIO); self.token_receiver.write(token_id, receiver); - let new_fees_ratio = if fees_ratio.denominator.is_zero() { - Default::default() - } else { - fees_ratio - }; - self.token_fees.write(token_id, new_fees_ratio); + self.token_fees.write(token_id, fees_ratio); self .emit( TokenRoyaltyUpdated { - token_id: token_id, fees_ratio: new_fees_ratio, receiver: receiver, + token_id: token_id, fees_ratio: fees_ratio, receiver: receiver, } ); } diff --git a/contracts/ark_oz/src/erc2981/fees.cairo b/contracts/ark_oz/src/erc2981/fees.cairo index 7c6eeb198..c681599c2 100644 --- a/contracts/ark_oz/src/erc2981/fees.cairo +++ b/contracts/ark_oz/src/erc2981/fees.cairo @@ -1,3 +1,5 @@ +const max_denominator: u256 = 10000; + #[derive(Serde, Drop, PartialEq, Copy, Debug, starknet::Store)] pub struct FeesRatio { numerator: u256, @@ -5,7 +7,8 @@ pub struct FeesRatio { } pub trait IFees { - fn compute_amount(self: T, sale_price: u256) -> u256; + fn compute_amount(self: @T, sale_price: u256) -> u256; + fn is_valid(self: @T) -> bool; } @@ -16,7 +19,13 @@ pub impl FeesRatioDefault of Default { } pub impl FeesImpl of IFees { - fn compute_amount(self: FeesRatio, sale_price: u256) -> u256 { - (sale_price * self.numerator) / self.denominator + fn compute_amount(self: @FeesRatio, sale_price: u256) -> u256 { + (sale_price * *self.numerator) / *self.denominator + } + + fn is_valid(self: @FeesRatio) -> bool { + (*self.numerator < *self.denominator) + && (*self).denominator.is_non_zero() + && (*self.denominator <= max_denominator) } } diff --git a/contracts/ark_oz/tests/test_erc2981.cairo b/contracts/ark_oz/tests/test_erc2981.cairo index 3ffccfe43..eed401606 100644 --- a/contracts/ark_oz/tests/test_erc2981.cairo +++ b/contracts/ark_oz/tests/test_erc2981.cairo @@ -26,6 +26,21 @@ fn setup_contract() -> (ContractAddress, ContractAddress, ContractAddress, FeesR (contract.deploy(@calldata).unwrap(), owner, receiver, default_fees) } +#[test] +fn test_fees_ratio_invalid() { + assert!(!FeesRatio { numerator: 0, denominator: 0, }.is_valid(), "Shall be invalid"); + + assert!(!FeesRatio { numerator: 30, denominator: 30, }.is_valid(), "Shall be invalid"); + + assert!(!FeesRatio { numerator: 40, denominator: 30, }.is_valid(), "Shall be invalid"); + + assert!(!FeesRatio { numerator: 5, denominator: 10000, }.is_valid(), "Shall be invalid"); + + assert!(!FeesRatio { numerator: 0, denominator: 0 }.is_valid(), "Shall be invalid"); + + assert!(FeesRatio { numerator: 0, denominator: 1, }.is_valid(), "Shall be valid"); +} + #[test] fn test_default_royalty() { let (contract_address, _, default_receiver, default_fees) = setup_contract(); From fb5e24eaedb21cb9aaea76f96ddb26f6cd2bec0b Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Fri, 5 Jul 2024 18:17:06 +0200 Subject: [PATCH 2/9] contracts(starknet): use FeesRatio.is_valid instead of custom implementation --- contracts/ark_starknet/src/executor.cairo | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/contracts/ark_starknet/src/executor.cairo b/contracts/ark_starknet/src/executor.cairo index 3e8cf4ef4..30858b7e7 100644 --- a/contracts/ark_starknet/src/executor.cairo +++ b/contracts/ark_starknet/src/executor.cairo @@ -144,7 +144,7 @@ mod executor { fn set_broker_fees( ref self: ContractState, broker_address: ContractAddress, fees_ratio: FeesRatio ) { - assert(_fees_ratio_is_valid(@fees_ratio), 'Fees ratio is invalid'); + assert(fees_ratio.is_valid(), 'Fees ratio is invalid'); self.broker_fees.write(broker_address, fees_ratio); } @@ -163,7 +163,7 @@ mod executor { starknet::get_caller_address() == self.admin_address.read(), 'Unauthorized admin address' ); - assert(_fees_ratio_is_valid(@fees_ratio), 'Fees ratio is invalid'); + assert(fees_ratio.is_valid(), 'Fees ratio is invalid'); self.ark_fees.write(fees_ratio); } @@ -183,7 +183,7 @@ mod executor { starknet::get_caller_address() == self.admin_address.read(), 'Unauthorized admin address' ); - assert(_fees_ratio_is_valid(@fees_ratio), 'Fees ratio is invalid'); + assert(fees_ratio.is_valid(), 'Fees ratio is invalid'); self.default_receiver.write(receiver); self.default_fees.write(fees_ratio); } @@ -209,7 +209,7 @@ mod executor { starknet::get_caller_address() == self.admin_address.read(), 'Unauthorized admin address' ); - assert(_fees_ratio_is_valid(@fees_ratio), 'Fees ratio is invalid'); + assert(fees_ratio.is_valid(), 'Fees ratio is invalid'); self.creator_fees.write(nft_address, (receiver, fees_ratio)); } @@ -749,8 +749,4 @@ mod executor { let amount = fees_ratio.compute_amount(payment_amount); (receiver, amount) } - - fn _fees_ratio_is_valid(fees_ratio: @FeesRatio) -> bool { - *fees_ratio.denominator != 0 && *fees_ratio.numerator < *fees_ratio.denominator - } } From e85b9f0bc080140d91c78c20d1689f9d16f593d9 Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Sun, 7 Jul 2024 11:40:44 +0200 Subject: [PATCH 3/9] feat(broker-fees): fees can only be set for caller --- contracts/ark_starknet/src/executor.cairo | 6 +- contracts/ark_starknet/src/interfaces.cairo | 2 +- .../tests/integration/execute_order.cairo | 64 ++++++++++++------- .../ark_starknet/tests/unit/test_fees.cairo | 22 ++++--- 4 files changed, 57 insertions(+), 37 deletions(-) diff --git a/contracts/ark_starknet/src/executor.cairo b/contracts/ark_starknet/src/executor.cairo index 30858b7e7..ef5e970a4 100644 --- a/contracts/ark_starknet/src/executor.cairo +++ b/contracts/ark_starknet/src/executor.cairo @@ -141,11 +141,9 @@ mod executor { #[abi(embed_v0)] impl ExecutorImpl of IExecutor { - fn set_broker_fees( - ref self: ContractState, broker_address: ContractAddress, fees_ratio: FeesRatio - ) { + fn set_broker_fees(ref self: ContractState, fees_ratio: FeesRatio) { assert(fees_ratio.is_valid(), 'Fees ratio is invalid'); - self.broker_fees.write(broker_address, fees_ratio); + self.broker_fees.write(starknet::get_caller_address(), fees_ratio); } fn get_broker_fees(self: @ContractState, broker_address: ContractAddress) -> FeesRatio { diff --git a/contracts/ark_starknet/src/interfaces.cairo b/contracts/ark_starknet/src/interfaces.cairo index f3b9203b7..f12c3ee80 100644 --- a/contracts/ark_starknet/src/interfaces.cairo +++ b/contracts/ark_starknet/src/interfaces.cairo @@ -19,7 +19,7 @@ trait IExecutor { fn get_messaging_address(self: @T) -> ContractAddress; fn get_orderbook_address(self: @T) -> ContractAddress; fn update_arkchain_orderbook_address(ref self: T, orderbook_address: ContractAddress); - fn set_broker_fees(ref self: T, broker_address: ContractAddress, fees_ratio: FeesRatio); + fn set_broker_fees(ref self: T, fees_ratio: FeesRatio); fn get_broker_fees(self: @T, broker_address: ContractAddress) -> FeesRatio; fn set_ark_fees(ref self: T, fees_ratio: FeesRatio); fn get_ark_fees(self: @T) -> FeesRatio; diff --git a/contracts/ark_starknet/tests/integration/execute_order.cairo b/contracts/ark_starknet/tests/integration/execute_order.cairo index 1cd8d2cb3..a18152a0e 100644 --- a/contracts/ark_starknet/tests/integration/execute_order.cairo +++ b/contracts/ark_starknet/tests/integration/execute_order.cairo @@ -160,13 +160,15 @@ fn test_execute_order_check_brokers_fees_ok() { let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let executor = IExecutorDispatcher { contract_address: executor_address }; - snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; - let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; - executor.set_broker_fees(fulfill_broker, fulfill_fees_ratio); - executor.set_broker_fees(listing_broker, listing_fees_ratio); + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); snf::stop_prank(CheatTarget::One(executor.contract_address)); assert_eq!( @@ -206,14 +208,20 @@ fn test_execute_order_check_ark_fees_ok() { let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let executor = IExecutorDispatcher { contract_address: executor_address }; - snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); let ark_fees_ratio = FeesRatio { numerator: 5, denominator: 1000 }; let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; - executor.set_broker_fees(fulfill_broker, fulfill_fees_ratio); - executor.set_broker_fees(listing_broker, listing_fees_ratio); + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); executor.set_ark_fees(ark_fees_ratio); snf::stop_prank(CheatTarget::One(executor.contract_address)); @@ -247,13 +255,16 @@ fn test_execute_order_erc2981_default_royalty_check_fees_ok() { let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let executor = IExecutorDispatcher { contract_address: executor_address }; - snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; - executor.set_broker_fees(fulfill_broker, fulfill_fees_ratio); - executor.set_broker_fees(listing_broker, listing_fees_ratio); + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); snf::stop_prank(CheatTarget::One(executor.contract_address)); assert_eq!( @@ -332,13 +343,16 @@ fn test_execute_order_erc2981_token_royalty_check_fees_ok() { let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let executor = IExecutorDispatcher { contract_address: executor_address }; - snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; - executor.set_broker_fees(fulfill_broker, fulfill_fees_ratio); - executor.set_broker_fees(listing_broker, listing_fees_ratio); + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); snf::stop_prank(CheatTarget::One(executor.contract_address)); assert_eq!( @@ -428,13 +442,15 @@ fn test_execute_order_non_erc2981_default_royalty_check_fees_ok() { let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let executor = IExecutorDispatcher { contract_address: executor_address }; - snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; - executor.set_broker_fees(fulfill_broker, fulfill_fees_ratio); - executor.set_broker_fees(listing_broker, listing_fees_ratio); + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); snf::stop_prank(CheatTarget::One(executor.contract_address)); assert_eq!( @@ -513,13 +529,15 @@ fn test_execute_order_non_erc2981_collection_royalty_check_fees_ok() { let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let executor = IExecutorDispatcher { contract_address: executor_address }; - snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; - executor.set_broker_fees(fulfill_broker, fulfill_fees_ratio); - executor.set_broker_fees(listing_broker, listing_fees_ratio); + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); snf::stop_prank(CheatTarget::One(executor.contract_address)); assert_eq!( @@ -597,13 +615,15 @@ fn test_execute_order_check_fee_too_much_fees() { let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let executor = IExecutorDispatcher { contract_address: executor_address }; - snf::start_prank(CheatTarget::One(executor.contract_address), admin_address); let fulfill_fees_ratio = FeesRatio { numerator: 60, denominator: 100 }; let listing_fees_ratio = FeesRatio { numerator: 60, denominator: 100 }; - executor.set_broker_fees(fulfill_broker, fulfill_fees_ratio); - executor.set_broker_fees(listing_broker, listing_fees_ratio); + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); snf::stop_prank(CheatTarget::One(executor.contract_address)); IExecutorDispatcher { contract_address: executor_address }.execute_order(execution_info); diff --git a/contracts/ark_starknet/tests/unit/test_fees.cairo b/contracts/ark_starknet/tests/unit/test_fees.cairo index 4ef0d6dad..55ba5321b 100644 --- a/contracts/ark_starknet/tests/unit/test_fees.cairo +++ b/contracts/ark_starknet/tests/unit/test_fees.cairo @@ -1,9 +1,10 @@ -use snforge_std::{test_address}; - use ark_starknet::executor::{executor}; use ark_starknet::interfaces::FeesRatio; use starknet::{ContractAddress}; +use starknet::testing; + +use snforge_std as snf; #[test] fn test_add_broker() { @@ -11,10 +12,11 @@ fn test_add_broker() { let fees_ratio = FeesRatio { numerator: 10, denominator: 100, }; - let broker_address = test_address(); + let broker_address = snf::test_address(); // Call the add_broker method. - executor::ExecutorImpl::set_broker_fees(ref state, broker_address, fees_ratio); + snf::start_prank(snf::CheatTarget::All, broker_address); + executor::ExecutorImpl::set_broker_fees(ref state, fees_ratio); let result = executor::ExecutorImpl::get_broker_fees(@state, broker_address); @@ -41,9 +43,9 @@ fn test_fees_ratio_bigger_than_1_broker_fees() { let fees_ratio = FeesRatio { numerator: 500, denominator: 100, }; - let broker_address = test_address(); - - executor::ExecutorImpl::set_broker_fees(ref state, broker_address, fees_ratio); + let broker_address = snf::test_address(); + snf::start_prank(snf::CheatTarget::All, broker_address); + executor::ExecutorImpl::set_broker_fees(ref state, fees_ratio); } #[test] @@ -63,9 +65,9 @@ fn test_fees_denominator_0_broker_fees() { let fees_ratio = FeesRatio { numerator: 10, denominator: 0, }; - let broker_address = test_address(); - - executor::ExecutorImpl::set_broker_fees(ref state, broker_address, fees_ratio); + let broker_address = snf::test_address(); + snf::start_prank(snf::CheatTarget::All, broker_address); + executor::ExecutorImpl::set_broker_fees(ref state, fees_ratio); } #[test] From 1073bc4fe5f423a63269e45e3c38411b5163090b Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Mon, 8 Jul 2024 11:14:53 +0200 Subject: [PATCH 4/9] contracts(orderbook): remove obsolete integration tests --- .../tests/integration/test_cancel_order.cairo | 169 -------- .../test_create_auction_offers.cairo | 72 ---- .../test_create_listing_order.cairo | 144 ------- .../integration/test_fulfill_auction.cairo | 346 ---------------- .../integration/test_fulfill_listing.cairo | 212 ---------- .../integration/test_fulfill_offers.cairo | 377 ------------------ 6 files changed, 1320 deletions(-) delete mode 100644 contracts/ark_orderbook/tests/integration/test_cancel_order.cairo delete mode 100644 contracts/ark_orderbook/tests/integration/test_create_auction_offers.cairo delete mode 100644 contracts/ark_orderbook/tests/integration/test_create_listing_order.cairo delete mode 100644 contracts/ark_orderbook/tests/integration/test_fulfill_auction.cairo delete mode 100644 contracts/ark_orderbook/tests/integration/test_fulfill_listing.cairo delete mode 100644 contracts/ark_orderbook/tests/integration/test_fulfill_offers.cairo diff --git a/contracts/ark_orderbook/tests/integration/test_cancel_order.cairo b/contracts/ark_orderbook/tests/integration/test_cancel_order.cairo deleted file mode 100644 index 2b2798549..000000000 --- a/contracts/ark_orderbook/tests/integration/test_cancel_order.cairo +++ /dev/null @@ -1,169 +0,0 @@ -use core::result::ResultTrait; -use core::traits::TryInto; -use core::traits::Into; -use core::option::OptionTrait; -use ark_common::crypto::{signer::{Signer, SignInfo}, hash::serialized_hash}; -use ark_common::protocol::order_types::{OrderStatus, OrderTrait, OrderType, CancelInfo, RouteType}; -use snforge_std::cheatcodes::CheatTarget; -use ark_orderbook::orderbook::Orderbook; -use ark_common::protocol::order_v1::OrderV1; -use ark_orderbook::orderbook::{OrderbookDispatcher, OrderbookDispatcherTrait}; -use starknet::deploy_syscall; -use snforge_std::{ - start_warp, declare, ContractClassTrait, spy_events, EventSpy, EventFetcher, EventAssertions, - Event, SpyOn, test_address, - signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl, StarkCurveVerifierImpl} -}; - -use super::super::common::setup::{ - setup_auction_order, setup_listing, sign_mock, setup_orders, setup_offer, - whitelist_creator_broker -}; - -#[test] -fn test_cancel_auction() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - - let (auction_listing_order, signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: signer); - - let cancel_info = CancelInfo { - order_hash: order_hash, - canceller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: auction_listing_order.token_id, - }; - - let cancel_info_hash = serialized_hash(cancel_info); - let canceller_signer = sign_mock(cancel_info_hash, auction_listing_order.offerer); - dispatcher.cancel_order(cancel_info, signer: canceller_signer); -} - -#[test] -#[should_panic(expected: ('OB: order not found',))] -fn test_cancel_non_existing_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (auction_listing_order, _, _, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - let order_hash = auction_listing_order.compute_order_hash(); - let canceller = 0x2284a6517b487be8114013f277f9e2010ac001a24a93e3c48cdf5f8f345a81b - .try_into() - .unwrap(); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let cancel_info = CancelInfo { - order_hash: order_hash, - canceller: canceller, - token_chain_id: 0, - token_address: 0x00E4769a4d2F7F69C70931A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(), - token_id: Option::Some(1), - }; - let cancel_info_hash = serialized_hash(cancel_info); - let canceller_signer = sign_mock(cancel_info_hash, canceller); - let dispatcher = OrderbookDispatcher { contract_address }; - dispatcher.cancel_order(cancel_info, signer: canceller_signer); -} - -#[test] -#[should_panic(expected: ('OB: auction is expired',))] -fn test_invalid_cancel_auction_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - - let (auction_listing_order, signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: signer); - - let order_type = dispatcher.get_order_type(order_hash); - assert(order_type == OrderType::Auction.into(), 'order is not auction'); - - let cancel_info = CancelInfo { - order_hash: order_hash, - canceller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: auction_listing_order.token_id - }; - - start_warp(CheatTarget::One(contract_address), end_date + 10); - - let cancel_info_hash = serialized_hash(cancel_info); - let canceller_signer = sign_mock(cancel_info_hash, auction_listing_order.offerer); - dispatcher.cancel_order(cancel_info, signer: canceller_signer); -} - -#[test] -fn test_cancel_auction_during_the_extended_time() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - - let (auction_listing_order, auction_listing_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: auction_listing_signer); - let order_type = dispatcher.get_order_type(order_hash); - assert(order_type == OrderType::Auction.into(), 'order is not auction'); - start_warp(CheatTarget::One(contract_address), end_date - 1); - let (auction_offer, signer, auction_order_hash, _) = setup_offer( - end_date - 1, end_date + 1200, Option::None, Option::None - ); - dispatcher.create_order(order: auction_offer, signer: signer); - let order_expiration_date = dispatcher.get_auction_expiration(auction_order_hash); - let expected_end_date = end_date + 600; - assert(order_expiration_date == expected_end_date, 'order end date is not correct'); - start_warp(CheatTarget::One(contract_address), end_date + 5); - let cancel_info = CancelInfo { - order_hash: order_hash, - canceller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: auction_listing_order.token_id - }; - - let cancel_info_hash = serialized_hash(cancel_info); - let canceller_signer = sign_mock(cancel_info_hash, auction_listing_order.offerer); - - dispatcher.cancel_order(cancel_info, signer: canceller_signer); -} diff --git a/contracts/ark_orderbook/tests/integration/test_create_auction_offers.cairo b/contracts/ark_orderbook/tests/integration/test_create_auction_offers.cairo deleted file mode 100644 index 2e78bc8f0..000000000 --- a/contracts/ark_orderbook/tests/integration/test_create_auction_offers.cairo +++ /dev/null @@ -1,72 +0,0 @@ -use core::result::ResultTrait; -use core::traits::TryInto; -use core::traits::Into; -use core::option::OptionTrait; -use ark_orderbook::orderbook::Orderbook; -use ark_common::crypto::{signer::{Signer, SignInfo}, hash::serialized_hash}; -use ark_common::protocol::order_types::{RouteType, FulfillInfo, OrderTrait, OrderType, OrderStatus}; -use snforge_std::cheatcodes::CheatTarget; -use ark_common::protocol::order_v1::OrderV1; -use ark_orderbook::orderbook::{OrderbookDispatcher, OrderbookDispatcherTrait}; -use starknet::deploy_syscall; -use snforge_std::{ - start_warp, declare, ContractClassTrait, spy_events, EventSpy, EventFetcher, EventAssertions, - Event, SpyOn, test_address, - signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl, StarkCurveVerifierImpl} -}; -use super::super::common::setup::{ - setup_auction_order, sign_mock, setup_orders, setup_offer, whitelist_creator_broker -}; - -#[test] -fn test_create_valid_auction_offer() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - - let (auction_listing_order, signer, _, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - let chain_id = 0x534e5f4d41494e; - let contract = declare('orderbook'); - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: signer); - - let (auction_offer, signer, _, _) = setup_offer( - start_date + 10, start_date + 50, Option::None, Option::None - ); - start_warp(CheatTarget::One(contract_address), start_date); - dispatcher.create_order(order: auction_offer, signer: signer); -} - -#[test] -fn test_accept_auction_after_expiration() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - - let (auction_listing_order, signer, _, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - let chain_id = 0x534e5f4d41494e; - let contract = declare('orderbook'); - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: signer); - - let (auction_offer, signer, _, _) = setup_offer( - start_date + 1000, start_date + 3000, Option::None, Option::None - ); - - start_warp(CheatTarget::One(contract_address), start_date); - dispatcher.create_order(order: auction_offer, signer: signer); -} diff --git a/contracts/ark_orderbook/tests/integration/test_create_listing_order.cairo b/contracts/ark_orderbook/tests/integration/test_create_listing_order.cairo deleted file mode 100644 index b9d88ea01..000000000 --- a/contracts/ark_orderbook/tests/integration/test_create_listing_order.cairo +++ /dev/null @@ -1,144 +0,0 @@ -use core::traits::TryInto; -use core::traits::Into; -use core::option::OptionTrait; -use ark_orderbook::orderbook::Orderbook; -use ark_common::crypto::{signer::{Signer, SignInfo}, hash::serialized_hash}; -use ark_common::protocol::order_types::{RouteType, FulfillInfo, OrderTrait, OrderType, OrderStatus}; -use snforge_std::cheatcodes::CheatTarget; -use ark_common::protocol::order_v1::OrderV1; -use ark_orderbook::orderbook::{OrderbookDispatcher, OrderbookDispatcherTrait}; -use starknet::deploy_syscall; -use super::super::common::setup::{ - setup_auction_order, setup_listing, sign_mock, setup_orders, setup_offer, - whitelist_creator_broker -}; -use snforge_std::{ - start_warp, declare, ContractClassTrait, spy_events, EventSpy, EventFetcher, EventAssertions, - Event, SpyOn, test_address, - signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl, StarkCurveVerifierImpl} -}; - -#[test] -#[should_panic(expected: ('OB: order already exists',))] -fn test_create_existing_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (order_listing, signer, _order_hash, _) = setup_listing( - start_date, end_date, Option::Some(123) - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - dispatcher.create_order(order: order_listing, signer: signer); - dispatcher.create_order(order: order_listing, signer: signer); -} - -#[test] -#[should_panic(expected: ('INVALID_BROKER',))] -fn test_create_order_not_whitelisted() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (order_listing, signer, _order_hash, _) = setup_listing( - start_date, end_date, Option::Some(123) - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - dispatcher.create_order(order: order_listing, signer: signer); -} - -#[test] -fn test_create_listing_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (order_listing, signer, _order_hash, token_hash) = setup_listing( - start_date, end_date, Option::Some(10) - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - dispatcher.create_order(order: order_listing, signer: signer); - let order = dispatcher.get_order(_order_hash); - let order_status = dispatcher.get_order_status(_order_hash); - let order_type = dispatcher.get_order_type(_order_hash); - let order_hash = dispatcher.get_order_hash(token_hash); - assert(order.broker_id == order_listing.broker_id, 'Broker id is not equal'); - assert(order.token_id.is_some(), 'No Token id'); - assert(order.token_id.unwrap() == 10, 'Token id is not equal'); - assert( - order - .token_address == 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - 'Token address is not equal' - ); - assert( - order - .currency_address == 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - 'Currency address is not equal' - ); - assert(order.quantity == 1, 'Quantity is not equal'); - assert(order.start_amount == 600000000000000000, 'Start amount is not equal'); - assert(order.end_amount == 0, 'End amount is not equal'); - assert(order.start_date == start_date, 'Start date is not equal'); - assert(order.end_date == end_date, 'End date is not equal'); - assert( - order - .offerer == 0x2284a6517b487be8114013f277f9e2010ac001a24a93e3c48cdf5f8f345a81b - .try_into() - .unwrap(), - 'Offerer is not equal' - ); - assert(order_hash == _order_hash, 'Order hash is not equal'); - assert(order_type == OrderType::Listing.into(), 'Order type is not listing'); - assert(order_status == OrderStatus::Open.into(), 'Order status is not open'); -} - -#[test] -fn test_auction_order_with_extended_time_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - - let (auction_listing_order, auction_listing_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: auction_listing_signer); - - let order_type = dispatcher.get_order_type(order_hash); - assert(order_type == OrderType::Auction.into(), 'order is not auction'); - - start_warp(CheatTarget::One(contract_address), end_date - 1); - let (auction_offer, signer, auction_order_hash, _) = setup_offer( - end_date - 1, end_date + 1200, Option::None, Option::None - ); - dispatcher.create_order(order: auction_offer, signer: signer); - let order_expiration_date = dispatcher.get_auction_expiration(auction_order_hash); - - let expected_end_date = end_date + 600; - assert(order_expiration_date == expected_end_date, 'order end date is not correct'); -} diff --git a/contracts/ark_orderbook/tests/integration/test_fulfill_auction.cairo b/contracts/ark_orderbook/tests/integration/test_fulfill_auction.cairo deleted file mode 100644 index dd9b3bdb0..000000000 --- a/contracts/ark_orderbook/tests/integration/test_fulfill_auction.cairo +++ /dev/null @@ -1,346 +0,0 @@ -use core::result::ResultTrait; -use core::debug::PrintTrait; -use core::traits::TryInto; -use core::traits::Into; -use core::option::OptionTrait; -use ark_orderbook::orderbook::Orderbook; -use ark_common::protocol::order_v1::OrderV1; -use ark_common::crypto::{signer::{Signer, SignInfo, SignerTrait}, hash::serialized_hash}; -use snforge_std::cheatcodes::CheatTarget; -use ark_common::protocol::order_types::{RouteType, FulfillInfo, OrderTrait, OrderType, OrderStatus}; -use ark_orderbook::orderbook::{OrderbookDispatcher, OrderbookDispatcherTrait}; -use starknet::deploy_syscall; -use snforge_std::{ - start_warp, declare, ContractClassTrait, spy_events, EventSpy, EventFetcher, EventAssertions, - Event, SpyOn, test_address, - signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl, StarkCurveVerifierImpl} -}; -use super::super::common::setup::{ - setup_auction_order, setup_listing, sign_mock, setup_orders, setup_offer, - whitelist_creator_broker -}; - -/// Test -/// -/// Create one auction one offer and fulfill it. -/// -#[test] -fn test_fulfill_auction() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - - let (auction_listing_order, auction_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: auction_signer); - - let (auction_offer, related_order_signer, related_order_hash, _) = setup_offer( - start_date, end_date, Option::None, Option::None - ); - - dispatcher.create_order(order: auction_offer, signer: related_order_signer); - - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::Some(related_order_hash), - fulfiller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: Option::Some(10), - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let offer_signer = sign_mock(fulfill_info_hash, auction_listing_order.offerer); - // sign original orderhash - // from signer send public key - dispatcher.fulfill_order(fulfill_info, offer_signer); -} - -/// Test -/// -/// Create one offer one auction and fulfill the auction with a classic offer. -/// -#[test] -fn test_fulfill_auction_with_classic_offer() { - // contract declaration - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - // Create an offer - let offer_start_date = starknet::get_block_timestamp(); - let offer_end_date = offer_start_date + (10 * 24 * 60 * 60); - let (offer_order, offer_signer, offer_order_hash, _) = setup_offer( - offer_start_date, offer_end_date, Option::None, Option::None - ); - whitelist_creator_broker(contract_address, offer_order.broker_id, dispatcher); - dispatcher.create_order(order: offer_order, signer: offer_signer); - - // Create an auction - let start_date = starknet::get_block_timestamp() + 1200; - let end_date = start_date + (10 * 24 * 60 * 60); - let (auction_listing_order, auction_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - dispatcher.create_order(order: auction_listing_order, signer: auction_signer); - - start_warp(CheatTarget::One(contract_address), start_date + 3600); - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::Some(offer_order_hash), - fulfiller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: Option::Some(10), - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, auction_listing_order.offerer); - dispatcher.fulfill_order(fulfill_info, signer); - let auction_status = dispatcher.get_order_status(order_hash); - let offer_status = dispatcher.get_order_status(offer_order_hash); - assert(auction_status == OrderStatus::Fulfilled.into(), 'Auction status is not fulfilled'); - assert(offer_status == OrderStatus::Fulfilled.into(), 'Offer status is not fulfilled'); -} - -// try to fulfill expired classic offer for a token when fulfilling an auction -#[should_panic(expected: ('OB: order expired',))] -#[test] -fn test_fulfill_auction_with_expired_offer() { - // contract declaration - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - // Create an offer - let offer_start_date = starknet::get_block_timestamp(); - let offer_end_date = offer_start_date + (10 * 24 * 60 * 60); - let (offer_order, offer_signer, offer_order_hash, _) = setup_offer( - offer_start_date, offer_end_date, Option::None, Option::None - ); - whitelist_creator_broker(contract_address, offer_order.broker_id, dispatcher); - - dispatcher.create_order(order: offer_order, signer: offer_signer); - - // Create an auction - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (auction_listing_order, auction_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - dispatcher.create_order(order: auction_listing_order, signer: auction_signer); - - start_warp(CheatTarget::One(contract_address), start_date + 3600); - - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::Some(offer_order_hash), - fulfiller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: Option::Some(10), - fulfill_broker_address: test_address(), - }; - start_warp(CheatTarget::One(contract_address), end_date); - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, auction_listing_order.offerer); - dispatcher.fulfill_order(fulfill_info, signer); -} - -// try to fullfill an expired auction -#[should_panic(expected: ('OB: order expired',))] -#[test] -fn test_fulfill_expired_auction() { - // contract declaration - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - // Create an offer - let offer_start_date = starknet::get_block_timestamp(); - let offer_end_date = offer_start_date + (10 * 24 * 60 * 60); - let (offer_order, offer_signer, offer_order_hash, _) = setup_offer( - offer_start_date, offer_end_date, Option::None, Option::None - ); - whitelist_creator_broker(contract_address, offer_order.broker_id, dispatcher); - dispatcher.create_order(order: offer_order, signer: offer_signer); - - // Create an auction - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (auction_listing_order, auction_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - dispatcher.create_order(order: auction_listing_order, signer: auction_signer); - - start_warp(CheatTarget::One(contract_address), end_date + 3600); - - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::Some(offer_order_hash), - fulfiller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: Option::Some(10), - fulfill_broker_address: test_address(), - }; - start_warp(CheatTarget::One(contract_address), 1700869684); - let fulfill_info_hash = serialized_hash(fulfill_info); - let fulfill_signer = sign_mock(fulfill_info_hash, auction_listing_order.offerer); - dispatcher.fulfill_order(fulfill_info, fulfill_signer); -} - -// try to fulfill an auction with an offer that is not for the same token -#[should_panic(expected: ('OB: token hash does not match',))] -#[test] -fn test_fulfill_auction_with_offer_for_different_token() { - // contract declaration - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - // Create an offer - let offer_start_date = starknet::get_block_timestamp(); - let offer_end_date = offer_start_date + (10 * 24 * 60 * 60); - let (mut offer_order, offer_signer, offer_order_hash, _) = setup_offer( - offer_start_date, offer_end_date, Option::None, Option::Some(42) - ); - whitelist_creator_broker(contract_address, offer_order.broker_id, dispatcher); - dispatcher.create_order(order: offer_order, signer: offer_signer); - - // Create an auction - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (auction_listing_order, auction_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - dispatcher.create_order(order: auction_listing_order, signer: auction_signer); - - start_warp(CheatTarget::One(contract_address), start_date + 3600); - - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::Some(offer_order_hash), - fulfiller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: Option::Some(11), - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, auction_listing_order.offerer); - dispatcher.fulfill_order(fulfill_info, signer); -} - -// try to fulfill an auction with a non existing related order hash -#[should_panic(expected: ('OB: order not found',))] -#[test] -fn test_fulfill_auction_with_non_existing_related_order_hash() { - // contract declaration - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - // Create an auction - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (auction_listing_order, auction_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: auction_signer); - - start_warp(CheatTarget::One(contract_address), start_date + 3600); - - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::Some(0x1234567890987654321), - fulfiller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: Option::Some(10), - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, auction_listing_order.offerer); - dispatcher.fulfill_order(fulfill_info, signer); -} - -// try to fulfill an auction with an order that is not an offer (a listing order) -#[should_panic(expected: ('OB: order is not an offer',))] -#[test] -fn test_fulfill_auction_with_listing_order() { - // contract declaration - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - // Create an auction - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (auction_listing_order, auction_signer, order_hash, _) = setup_auction_order( - start_date, end_date, 1, 10, Option::None - ); - whitelist_creator_broker(contract_address, auction_listing_order.broker_id, dispatcher); - dispatcher.create_order(order: auction_listing_order, signer: auction_signer); - - //create a listing order - let (listing_order, listing_signer, listing_order_hash, _) = setup_listing( - start_date, end_date, Option::Some(123) - ); - whitelist_creator_broker(contract_address, listing_order.broker_id, dispatcher); - dispatcher.create_order(order: listing_order, signer: listing_signer); - - start_warp(CheatTarget::One(contract_address), start_date + 3600); - - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::Some(listing_order_hash), - fulfiller: auction_listing_order.offerer, - token_chain_id: auction_listing_order.token_chain_id, - token_address: auction_listing_order.token_address, - token_id: Option::Some(10), - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, auction_listing_order.offerer); - dispatcher.fulfill_order(fulfill_info, signer); -} diff --git a/contracts/ark_orderbook/tests/integration/test_fulfill_listing.cairo b/contracts/ark_orderbook/tests/integration/test_fulfill_listing.cairo deleted file mode 100644 index 6c666be4b..000000000 --- a/contracts/ark_orderbook/tests/integration/test_fulfill_listing.cairo +++ /dev/null @@ -1,212 +0,0 @@ -use core::result::ResultTrait; -use core::traits::TryInto; -use core::traits::Into; -use core::option::OptionTrait; -use snforge_std::{declare, ContractClassTrait}; -use ark_orderbook::orderbook::Orderbook; -use ark_orderbook::orderbook::orderbook; -use ark_common::protocol::order_v1::OrderV1; -use snforge_std::cheatcodes::CheatTarget; -use ark_common::crypto::{signer::{Signer, SignInfo, SignerTrait}, hash::serialized_hash}; -use ark_common::protocol::order_types::{RouteType, FulfillInfo, OrderTrait, OrderType, OrderStatus}; -use ark_orderbook::orderbook::{OrderbookDispatcher, OrderbookDispatcherTrait}; -use starknet::deploy_syscall; -use snforge_std::{start_warp, test_address}; - -use super::super::common::signer::sign_mock; -use super::super::common::setup::{ - setup_listing, setup_listing_order_with_sign, whitelist_creator_broker -}; - -// try to fulfill an order that doesn't exist -#[should_panic(expected: ('OB: order not found',))] -#[test] -fn test_create_listing_order_and_fulfill_non_existing_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (_, _, _order_hash, _) = setup_listing(start_date, end_date, Option::Some(123)); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - - let dispatcher = OrderbookDispatcher { contract_address }; - let fulfiller = 0x00E4769a4d2F7F69C70951A333eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(); - let fulfill_info = FulfillInfo { - order_hash: 0x00E4769a444F7FF9C70951A333eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(), - related_order_hash: Option::None, - fulfiller: fulfiller, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(8), - fulfill_broker_address: test_address() - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfiller); - - dispatcher.fulfill_order(fulfill_info, signer); -} - -// create and order & fulfill it -#[test] -fn test_create_listing_order_and_fulfill() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (order_listing, signer, order_hash, _) = setup_listing( - start_date, end_date, Option::Some(123) - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - dispatcher.create_order(order: order_listing, signer: signer); - let fulfiller = 0x00E4769a4d2F7F69C70931A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(); - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::None, - fulfiller: fulfiller, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(10), - fulfill_broker_address: test_address() - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfiller); - - dispatcher.fulfill_order(fulfill_info, signer); - - let order_status = dispatcher.get_order_status(order_hash); - - assert(order_status == OrderStatus::Fulfilled.into(), 'Status should be fulfilled'); -} - -// try to fulfill an order with the same fulfiller as the order creator -#[should_panic(expected: ('OB: order has same offerer',))] -#[test] -fn test_create_listing_order_and_fulfill_with_same_fulfiller() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (order_listing, signer, order_hash, _) = setup_listing( - start_date, end_date, Option::Some(123) - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - dispatcher.create_order(order: order_listing, signer: signer); - - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::None, - fulfiller: order_listing.offerer, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(10), - fulfill_broker_address: test_address() - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, order_listing.offerer); - - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[should_panic(expected: ('OB: order not fulfillable',))] -#[test] -fn test_fulfill_already_fulfilled_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (order_listing, signer, order_hash, _) = setup_listing( - start_date, end_date, Option::Some(123) - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - - dispatcher.create_order(order: order_listing, signer: signer); - let fulfiller = 0x00E4769a4d2F7F69C70931A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(); - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::None, - fulfiller: fulfiller, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(10), - fulfill_broker_address: test_address() - }; - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[should_panic(expected: ('OB: order expired',))] -#[test] -fn test_fulfill_expired_order() { - let start_date = starknet::get_block_timestamp(); - let end_date = start_date + (10 * 24 * 60 * 60); - let (order_listing, signer, order_hash, _) = setup_listing( - start_date, end_date, Option::Some(123) - ); - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - dispatcher.create_order(order: order_listing, signer: signer); - - start_warp(CheatTarget::One(contract_address), order_listing.end_date + 10); - let fulfiller = 0x00E4269a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(); - let fulfill_info = FulfillInfo { - order_hash: order_hash, - related_order_hash: Option::None, - fulfiller: fulfiller, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(10), - fulfill_broker_address: test_address() - }; - let fulfill_info_hash = serialized_hash(fulfill_info); - let fulfill_signer = sign_mock(fulfill_info_hash, fulfiller); - dispatcher.fulfill_order(fulfill_info, fulfill_signer); -} diff --git a/contracts/ark_orderbook/tests/integration/test_fulfill_offers.cairo b/contracts/ark_orderbook/tests/integration/test_fulfill_offers.cairo deleted file mode 100644 index 0bcfcaa4b..000000000 --- a/contracts/ark_orderbook/tests/integration/test_fulfill_offers.cairo +++ /dev/null @@ -1,377 +0,0 @@ -use core::result::ResultTrait; -use core::traits::TryInto; -use core::traits::Into; -use core::option::OptionTrait; -use ark_orderbook::orderbook::Orderbook; -use ark_orderbook::orderbook::orderbook; -use ark_common::protocol::order_v1::OrderV1; -use ark_common::crypto::{signer::{Signer, SignInfo, SignerTrait}, hash::serialized_hash}; -use snforge_std::cheatcodes::CheatTarget; -use ark_common::protocol::order_types::{RouteType, FulfillInfo, OrderTrait, OrderType, OrderStatus}; -use ark_orderbook::orderbook::{OrderbookDispatcher, OrderbookDispatcherTrait}; -use starknet::deploy_syscall; -use snforge_std::{ - start_warp, declare, ContractClassTrait, spy_events, EventSpy, EventFetcher, EventAssertions, - Event, SpyOn, test_address, - signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl, StarkCurveVerifierImpl} -}; - -use super::super::common::signer::sign_mock; -use super::super::common::setup::{ - setup_orders, setup_listing_order_with_sign, whitelist_creator_broker -}; - -#[test] -#[should_panic(expected: ('OB: order expired',))] -fn test_fulfill_expired_offer() { - let (order_listing, mut order_offer, _, _) = setup_orders(); - let chain_id = 0x534e5f4d41494e; - let contract = declare('orderbook'); - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - order_offer.start_date = order_listing.start_date; - order_offer.end_date = order_listing.start_date + 1000; - - let offer_order_hash = order_offer.compute_order_hash(); - let offer_signer = sign_mock(offer_order_hash, order_offer.offerer); - whitelist_creator_broker(contract_address, order_offer.broker_id, dispatcher); - dispatcher.create_order(order: order_offer, signer: offer_signer); - - start_warp(CheatTarget::One(contract_address), order_listing.start_date + 2000); - - let fulfill_info = FulfillInfo { - order_hash: order_offer.compute_order_hash(), - related_order_hash: Option::None, - fulfiller: order_listing.offerer, - token_chain_id: order_listing.token_chain_id, - token_address: order_listing.token_address, - token_id: order_listing.token_id, - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[test] -#[should_panic(expected: ('OB: order not found',))] -fn test_fulfill_non_existing_offer() { - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - let order_hash: felt252 = 0x0123456.into(); - let fulfill_info = FulfillInfo { - order_hash, - related_order_hash: Option::None, - fulfiller: 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(), - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(10), - fulfill_broker_address: test_address() - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[test] -fn test_fulfill_classic_offer() { - let (order_listing, mut order_offer, _, _) = setup_orders(); - - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - let listing_order_hash = order_listing.compute_order_hash(); - let signer = sign_mock(listing_order_hash, order_listing.offerer); - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - dispatcher.create_order(order: order_listing, signer: signer); - - order_offer.start_date = order_listing.start_date; - order_offer.end_date = order_listing.start_date + 1000; - - let offer_order_hash = order_offer.compute_order_hash(); - let offer_signer = sign_mock(offer_order_hash, order_offer.offerer); - dispatcher.create_order(order: order_offer, signer: offer_signer); - - start_warp(CheatTarget::One(contract_address), order_offer.start_date); - - let fulfill_info = FulfillInfo { - order_hash: order_offer.compute_order_hash(), - related_order_hash: Option::None, - fulfiller: order_listing.offerer, - token_chain_id: order_listing.token_chain_id, - token_address: order_listing.token_address, - token_id: order_listing.token_id, - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[test] -fn test_fulfill_collection_offer() { - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - let data = array![]; - let data_span = data.span(); - - let order_offer = OrderV1 { - route: RouteType::Erc20ToErc721.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: chain_id, - salt: 1, - offerer: 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(), - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::None, - quantity: 1, - start_amount: 600000000000000000, - end_amount: 0, - start_date: 100, - end_date: 1000, - broker_id: test_address(), - additional_data: data_span, - }; - - let offer_order_hash = order_offer.compute_order_hash(); - let offer_signer = sign_mock(offer_order_hash, order_offer.offerer); - whitelist_creator_broker(contract_address, order_offer.broker_id, dispatcher); - dispatcher.create_order(order: order_offer, signer: offer_signer); - - start_warp(CheatTarget::One(contract_address), order_offer.start_date); - - let fulfill_info = FulfillInfo { - order_hash: order_offer.compute_order_hash(), - related_order_hash: Option::None, - fulfiller: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc8 - .try_into() - .unwrap(), - token_chain_id: 0x534e5f4d41494e.try_into().unwrap(), - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(1), - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[test] -#[should_panic(expected: ('OB: order expired',))] -fn test_fulfill_expired_collection_offer() { - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - let data = array![]; - let data_span = data.span(); - - let order_offer = OrderV1 { - route: RouteType::Erc20ToErc721.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: chain_id, - salt: 1, - offerer: 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(), - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::None, - quantity: 1, - start_amount: 600000000000000000, - end_amount: 0, - start_date: 100, - end_date: 1000, - broker_id: test_address(), - additional_data: data_span, - }; - - let offer_order_hash = order_offer.compute_order_hash(); - let offer_signer = sign_mock(offer_order_hash, order_offer.offerer); - whitelist_creator_broker(contract_address, order_offer.broker_id, dispatcher); - dispatcher.create_order(order: order_offer, signer: offer_signer); - - start_warp(CheatTarget::One(contract_address), order_offer.end_date); - - let fulfill_info = FulfillInfo { - order_hash: order_offer.compute_order_hash(), - related_order_hash: Option::None, - fulfiller: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc8 - .try_into() - .unwrap(), - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(1), - fulfill_broker_address: test_address() - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[test] -#[should_panic(expected: ('OB: token id is missing',))] -fn test_fulfill_collection_offer_andatory_token_id() { - let contract = declare('orderbook'); - let chain_id = 0x534e5f4d41494e; - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - let data = array![]; - let data_span = data.span(); - - let order_offer = OrderV1 { - route: RouteType::Erc20ToErc721.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: chain_id, - salt: 1, - offerer: 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(), - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::None, - quantity: 1, - start_amount: 600000000000000000, - end_amount: 0, - start_date: starknet::get_block_timestamp(), - end_date: starknet::get_block_timestamp() + 1000, - broker_id: test_address(), - additional_data: data_span, - }; - - let offer_order_hash = order_offer.compute_order_hash(); - let offer_signer = sign_mock(offer_order_hash, order_offer.offerer); - whitelist_creator_broker(contract_address, order_offer.broker_id, dispatcher); - dispatcher.create_order(order: order_offer, signer: offer_signer); - - start_warp(CheatTarget::One(contract_address), order_offer.end_date); - - let fulfill_info = FulfillInfo { - order_hash: order_offer.compute_order_hash(), - related_order_hash: Option::None, - fulfiller: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc8 - .try_into() - .unwrap(), - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::None, - fulfill_broker_address: test_address() - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); -} - -#[test] -#[should_panic(expected: ('OB: order not fulfillable',))] -fn test_double_fulfill_offer() { - let (order_listing, mut order_offer, _, _) = setup_orders(); - let chain_id = 0x534e5f4d41494e; - let contract = declare('orderbook'); - let contract_data = array![ - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078, chain_id - ]; - let contract_address = contract.deploy(@contract_data).unwrap(); - let dispatcher = OrderbookDispatcher { contract_address }; - - let listing_order_hash = order_listing.compute_order_hash(); - let signer = sign_mock(listing_order_hash, order_listing.offerer); - whitelist_creator_broker(contract_address, order_listing.broker_id, dispatcher); - - dispatcher.create_order(order: order_listing, signer: signer); - - order_offer.start_date = order_listing.start_date; - order_offer.end_date = order_listing.start_date + 1000; - - let offer_order_hash = order_offer.compute_order_hash(); - let offer_signer = sign_mock(offer_order_hash, order_offer.offerer); - dispatcher.create_order(order: order_offer, signer: offer_signer); - - start_warp(CheatTarget::One(contract_address), order_offer.start_date); - - let fulfill_info = FulfillInfo { - order_hash: order_offer.compute_order_hash(), - related_order_hash: Option::None, - fulfiller: order_listing.offerer, - token_chain_id: order_listing.token_chain_id, - token_address: order_listing.token_address, - token_id: order_listing.token_id, - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); - - let fulfill_info = FulfillInfo { - order_hash: order_offer.compute_order_hash(), - related_order_hash: Option::None, - fulfiller: order_listing.offerer, - token_chain_id: order_listing.token_chain_id, - token_address: order_listing.token_address, - token_id: order_listing.token_id, - fulfill_broker_address: test_address(), - }; - - let fulfill_info_hash = serialized_hash(fulfill_info); - let signer = sign_mock(fulfill_info_hash, fulfill_info.fulfiller); - dispatcher.fulfill_order(fulfill_info, signer); -} From 08f24f45cefc6ab6bb9d1b4e5f2b488ea68a0b72 Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Mon, 8 Jul 2024 16:25:54 +0200 Subject: [PATCH 5/9] contracts(orderbook): remove broker whitelist Remove dead code --- contracts/ark_common/src/lib.cairo | 1 - .../ark_common/src/protocol/broker.cairo | 70 ------- .../ark_common/src/protocol/order_types.cairo | 4 - .../ark_common/src/protocol/order_v1.cairo | 11 - contracts/ark_orderbook/src/orderbook.cairo | 191 ------------------ .../ark_orderbook/tests/common/setup.cairo | 188 ----------------- .../ark_orderbook/tests/common/signer.cairo | 22 -- contracts/ark_orderbook/tests/lib.cairo | 10 - .../tests/unit/order/test_order_v1.cairo | 9 +- 9 files changed, 3 insertions(+), 503 deletions(-) delete mode 100644 contracts/ark_common/src/protocol/broker.cairo delete mode 100644 contracts/ark_orderbook/tests/common/signer.cairo diff --git a/contracts/ark_common/src/lib.cairo b/contracts/ark_common/src/lib.cairo index cf570b796..54eb951bc 100644 --- a/contracts/ark_common/src/lib.cairo +++ b/contracts/ark_common/src/lib.cairo @@ -2,7 +2,6 @@ mod protocol { mod order_types; mod order_v1; mod order_database; - mod broker; } mod crypto { diff --git a/contracts/ark_common/src/protocol/broker.cairo b/contracts/ark_common/src/protocol/broker.cairo deleted file mode 100644 index 4356fcd09..000000000 --- a/contracts/ark_common/src/protocol/broker.cairo +++ /dev/null @@ -1,70 +0,0 @@ -//! Orders database. -//! -//! The order database uses the `storage_read` and `storage_write` -//! syscalls directly to optimize how data are stored. -//! -//! The status is always stored independently of the seriliazed -//! broker. This allows a quick and cheap storage/retrieval of the status -//! without having to write/read the whole order. -//! -//! The only assumption for now is that, -//! a single order serialized buffer must not exceed -//! 256 felts. -//! -//! The storage layout is the following: -//! -//! 1. Compute the storage base address with [BROKER_DB_BASE_KEY, broker_id] -//! 2. At base address => The broker whitelisting status. -use starknet::SyscallResultTrait; -use starknet::ContractAddress; -use starknet::contract_address_to_felt252; - - -/// Must remain equal to 0 for now. -const ADDRESS_DOMAIN: u32 = 0; -/// A constant value used in the base key hash. -const BROKER_DB_BASE_KEY: felt252 = 'broker whitelist'; - - -/// Reads whitelist status of broker. -/// -/// # Arguments -/// -/// * `broker_id` - ID of the broker. -fn broker_whitelist_read(broker_id: ContractAddress) -> bool { - let key = array![BROKER_DB_BASE_KEY, contract_address_to_felt252(broker_id)]; - - let base = starknet::storage_base_address_from_felt252( - poseidon::poseidon_hash_span(key.span()) - ); - - // First offset is the status. - let whitelisted: felt252 = starknet::storage_read_syscall( - ADDRESS_DOMAIN, starknet::storage_address_from_base(base) - ) - .unwrap_syscall(); - - whitelisted == 1 -} - -/// Writes only the whitelisted brokers. -/// It can be whitelisted or blacklisted. -/// -/// # Arguments -/// -/// * `broker_id` - ID of the broker. -/// * `status` - 1 if whitelisted, 0 if not. -fn broker_whitelist_write(broker_id: ContractAddress, status: felt252) -> bool { - let key = array![BROKER_DB_BASE_KEY, contract_address_to_felt252(broker_id)]; - - let base = starknet::storage_base_address_from_felt252( - poseidon::poseidon_hash_span(key.span()) - ); - - starknet::storage_write_syscall( - ADDRESS_DOMAIN, starknet::storage_address_from_base(base), status - ) - .unwrap_syscall(); - - true -} diff --git a/contracts/ark_common/src/protocol/order_types.cairo b/contracts/ark_common/src/protocol/order_types.cairo index 6811f1e1f..536d8ef6e 100644 --- a/contracts/ark_common/src/protocol/order_types.cairo +++ b/contracts/ark_common/src/protocol/order_types.cairo @@ -50,7 +50,6 @@ enum OrderValidationError { AdditionalDataTooLong, InvalidContent, InvalidSalt, - InvalidBroker, } impl OrderValidationErrorIntoFelt252 of Into { @@ -61,7 +60,6 @@ impl OrderValidationErrorIntoFelt252 of Into { OrderValidationError::AdditionalDataTooLong => 'ADDITIONAL_DATA_TOO_LONG', OrderValidationError::InvalidContent => 'INVALID_CONTENT', OrderValidationError::InvalidSalt => 'INVALID_SALT', - OrderValidationError::InvalidBroker => 'INVALID_BROKER', } } } @@ -78,8 +76,6 @@ impl Felt252TryIntoOrderValidationError of TryInto end_amount (reserve price) > start_amount (starting price). // Auction -> ERC721_ERC20. @@ -96,13 +92,6 @@ impl OrderTraitOrderV1 of OrderTrait { return Result::Err(OrderValidationError::InvalidContent); } - // check if the broker is whitelisted. - let whitelisted = broker_whitelist_read(*self.broker_id); - - if whitelisted == false { - return Result::Err(OrderValidationError::InvalidBroker); - } - Result::Ok(()) } diff --git a/contracts/ark_orderbook/src/orderbook.cairo b/contracts/ark_orderbook/src/orderbook.cairo index 01b6e0a9c..f717f6c45 100644 --- a/contracts/ark_orderbook/src/orderbook.cairo +++ b/contracts/ark_orderbook/src/orderbook.cairo @@ -13,44 +13,6 @@ use starknet::ContractAddress; /// Orderbook trait to define operations on orderbooks. #[starknet::interface] trait Orderbook { - /// Whitelists a broker. - /// - /// # Arguments - /// - /// * `broker_id` - ID of the broker. - fn whitelist_broker(ref self: T, broker_id: ContractAddress); - - /// Remove a broker from the whitelist. - /// - /// # Arguments - /// - /// * `broker_id` - ID of the broker. - fn unwhitelist_broker(ref self: T, broker_id: ContractAddress); - - /// Submits and places an order to the orderbook if the order is valid. - /// - /// # Arguments - /// - /// * `order` - The order to be placed. - /// * `sign_info` - The signing info of the `order`. - fn create_order(ref self: T, order: OrderV1, signer: Signer); - - /// Cancels an existing order in the orderbook. - /// - /// # Arguments - /// - /// * `cancel_info` - information about the order to be cancelled. - /// * `sign_info` - The signing information associated with the order cancellation. - fn cancel_order(ref self: T, cancel_info: CancelInfo, signer: Signer); - - /// Fulfils an existing order in the orderbook. - /// - /// # Arguments - /// - /// * `order_hash` - The order to be fulfil. - /// * `sign_info` - The signing information associated with the order fulfillment. - fn fulfill_order(ref self: T, fulfill_info: FulfillInfo, signer: Signer); - /// Retrieves the type of an order using its hash. /// /// # Arguments @@ -75,12 +37,6 @@ trait Orderbook { /// * `order_hash` - The order hash of order. fn get_order(self: @T, order_hash: felt252) -> OrderV1; - /// Retrieves the order signer using its hash. - /// - /// # Arguments - /// * `order_hash` - The order hash of order. - fn get_order_signer(self: @T, order_hash: felt252) -> felt252; - /// Retrieves the order hash using its token hash. /// /// # Arguments @@ -153,8 +109,6 @@ mod orderbook { order_read, order_status_read, order_write, order_status_write, order_type_read }; - use ark_common::protocol::broker::{broker_whitelist_write}; - const EXTENSION_TIME_IN_SECONDS: u64 = 600; const AUCTION_ACCEPTING_TIME_SECS: u64 = 172800; /// Storage struct for the Orderbook contract. @@ -176,8 +130,6 @@ mod orderbook { auctions: LegacyMap, /// Mapping of auction offer order_hash to auction listing order_hash. auction_offers: LegacyMap, - /// Mapping of order_hash to order_signer public key. - order_signers: LegacyMap, /// The address of the StarkNet executor contract. starknet_executor_address: ContractAddress, } @@ -377,16 +329,6 @@ mod orderbook { order.unwrap() } - /// Retrieves the order signer using its hash. - /// # View - fn get_order_signer(self: @ContractState, order_hash: felt252) -> felt252 { - let order_signer = self.order_signers.read(order_hash); - if (order_signer.is_zero()) { - panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND); - } - order_signer - } - /// Retrieves the order hash using its token hash. /// # View fn get_order_hash(self: @ContractState, token_hash: felt252) -> felt252 { @@ -396,139 +338,6 @@ mod orderbook { } order_hash } - - /// Whitelists a broker. - fn whitelist_broker(ref self: ContractState, broker_id: ContractAddress) { - assert(starknet::get_caller_address() == self.admin.read(), 'Unauthorized update'); - broker_whitelist_write(broker_id, 1); - } - - /// Remove a broker from whitelist. - fn unwhitelist_broker(ref self: ContractState, broker_id: ContractAddress) { - assert(starknet::get_caller_address() == self.admin.read(), 'Unauthorized update'); - broker_whitelist_write(broker_id, 0); - } - - /// Submits and places an order to the orderbook if the order is valid. - fn create_order(ref self: ContractState, order: OrderV1, signer: Signer) { - let order_hash = order.compute_order_hash(); - let order_sign = OrderSign { hash: order_hash }; - let order_sign_hash = order_sign - .compute_hash_from(from: order.offerer, chain_id: self.chain_id.read()); - let user_pubkey = SignerValidator::verify(order_sign_hash, signer); - let block_ts = starknet::get_block_timestamp(); - let validation = order.validate_common_data(block_ts); - if validation.is_err() { - panic_with_felt252(validation.unwrap_err().into()); - } - let order_type = order - .validate_order_type() - .expect(orderbook_errors::ORDER_INVALID_DATA); - let order_hash = order.compute_order_hash(); - match order_type { - OrderType::Listing => { - assert( - order_status_read(order_hash).is_none(), - orderbook_errors::ORDER_ALREADY_EXISTS - ); - let _ = self._create_listing_order(order, order_type, order_hash); - }, - OrderType::Auction => { - assert( - order_status_read(order_hash).is_none(), - orderbook_errors::ORDER_ALREADY_EXISTS - ); - self._create_auction(order, order_type, order_hash); - }, - OrderType::Offer => { self._create_offer(order, order_type, order_hash); }, - OrderType::CollectionOffer => { - self._create_collection_offer(order, order_type, order_hash); - }, - }; - self.order_signers.write(order_hash, user_pubkey); - } - - fn cancel_order(ref self: ContractState, cancel_info: CancelInfo, signer: Signer) { - let order_hash = cancel_info.order_hash; - let original_signer_public_key = self.order_signers.read(order_hash); - let mut canceller_signer = signer.clone(); - canceller_signer.set_public_key(original_signer_public_key); - let cancel_info_hash = serialized_hash(cancel_info); - let order_sign = OrderSign { hash: cancel_info_hash }; - let order_sign_hash = order_sign - .compute_hash_from(from: cancel_info.canceller, chain_id: self.chain_id.read()); - - SignerValidator::verify(order_sign_hash, canceller_signer); - let order_option = order_read::(order_hash); - assert(order_option.is_some(), orderbook_errors::ORDER_NOT_FOUND); - let order = order_option.unwrap(); - assert(order.offerer == cancel_info.canceller, 'not the same offerrer'); - match order_status_read(order_hash) { - Option::Some(s) => s, - Option::None => panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND), - }; - let block_ts = starknet::get_block_timestamp(); - match order_type_read(order_hash) { - Option::Some(order_type) => { - if order_type == OrderType::Auction { - let auction_token_hash = order.compute_token_hash(); - let (_, auction_end_date, _) = self.auctions.read(auction_token_hash); - assert( - block_ts <= auction_end_date, orderbook_errors::ORDER_AUCTION_IS_EXPIRED - ); - self.auctions.write(auction_token_hash, (0, 0, 0)); - } else { - assert(block_ts < order.end_date, orderbook_errors::ORDER_IS_EXPIRED); - if order_type == OrderType::Listing { - self.token_listings.write(order.compute_token_hash(), 0); - } - } - }, - Option::None => panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND), - }; - - // Cancel order - order_status_write(order_hash, OrderStatus::CancelledUser); - self.emit(OrderCancelled { order_hash, reason: OrderStatus::CancelledUser.into() }); - } - - fn fulfill_order(ref self: ContractState, fulfill_info: FulfillInfo, signer: Signer) { - let fulfill_hash = serialized_hash(fulfill_info); - let fulfill_sign = OrderSign { hash: fulfill_hash }; - let fulfill_sign_hash = fulfill_sign - .compute_hash_from(from: fulfill_info.fulfiller, chain_id: self.chain_id.read()); - - SignerValidator::verify(fulfill_sign_hash, signer); - - let order_hash = fulfill_info.order_hash; - let order: OrderV1 = match order_read(order_hash) { - Option::Some(o) => o, - Option::None => panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND), - }; - let status = match order_status_read(order_hash) { - Option::Some(s) => s, - Option::None => panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND), - }; - assert(status == OrderStatus::Open, orderbook_errors::ORDER_NOT_FULFILLABLE); - let order_type = match order_type_read(order_hash) { - Option::Some(s) => s, - Option::None => panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND), - }; - match order_type { - OrderType::Listing => { self._fulfill_listing_order(fulfill_info, order); }, - OrderType::Auction => { - let original_signer_public_key = self - .order_signers - .read(fulfill_info.order_hash); - let mut origin_signer = signer.clone(); - origin_signer.set_public_key(original_signer_public_key); - SignerValidator::verify(fulfill_sign_hash, origin_signer); - self._fulfill_auction_order(fulfill_info, order) - }, - OrderType::Offer => { self._fulfill_offer(fulfill_info, order); }, - OrderType::CollectionOffer => { self._fulfill_offer(fulfill_info, order); } - } - } } // ************************************************************************* diff --git a/contracts/ark_orderbook/tests/common/setup.cairo b/contracts/ark_orderbook/tests/common/setup.cairo index 7ee45cb22..27349582a 100644 --- a/contracts/ark_orderbook/tests/common/setup.cairo +++ b/contracts/ark_orderbook/tests/common/setup.cairo @@ -14,7 +14,6 @@ use snforge_std::signature::stark_curve::{ use snforge_std::{start_prank, stop_prank, test_address, CheatTarget}; use starknet::ContractAddress; -use super::super::common::signer::sign_mock; /// Utility function to setup orders for test environment. /// /// # Returns a tuple of the different orders @@ -126,57 +125,6 @@ fn setup_orders() -> (OrderV1, OrderV1, OrderV1, OrderV1,) { (order_listing, order_offer, order_auction, order_collection_offer) } -/// Utility function to setup offer for test environment. -/// -/// # Returns a tuple of the different orders -/// * order_offer - An offer order of type OrderV1 -/// * signer - A signer of type Signer -/// * order_hash - The order hash of type felt252 -/// * token_hash - The token hash of type felt252 -fn setup_offer( - start_date: u64, end_date: u64, pk: Option, token_id: Option -) -> (OrderV1, Signer, felt252, felt252) { - let mut _token_id = 10; - let chain_id = 0x534e5f4d41494e; - if token_id.is_some() { - _token_id = token_id.unwrap(); - } - - let data = array![]; - let data_span = data.span(); - let offerer = 0x202344517b487be8114013f277f9e2010ac001a24a93e3c48cdf5f8f345a81b - .try_into() - .unwrap(); - let order_offer = OrderV1 { - route: RouteType::Erc20ToErc721.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: chain_id, - salt: 1, - offerer: offerer, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(_token_id), - quantity: 1, - start_amount: 600000000000000000, - end_amount: 0, - start_date, - end_date, - broker_id: 0x123.try_into().unwrap(), - additional_data: data_span, - }; - - let order_hash = order_offer.compute_order_hash(); - let token_hash = order_offer.compute_token_hash(); - - let signer = sign_mock(order_hash, offerer); - - (order_offer, signer, order_hash, token_hash) -} - /// Utility function to setup a listing order for test environment. /// /// # Arguments @@ -218,131 +166,6 @@ fn setup_listing_order(price: felt252) -> (OrderV1, felt252, felt252) { (order_listing, order_hash, token_hash) } -/// Utility function to setup a listing order for test environment. -/// -/// # Returns a tuple of the different orders data -/// -/// * order_listing -/// * sign_info -/// * order_hash -/// *token_hash -/// -fn setup_listing_order_with_sign() -> (OrderV1, SignInfo, felt252, felt252) { - let block_timestamp = starknet::get_block_timestamp(); - let end_date = block_timestamp + (30 * 24 * 60 * 60); - let data = array![]; - let chain_id = 0x534e5f4d41494e; - let data_span = data.span(); - let order_listing = OrderV1 { - route: RouteType::Erc721ToErc20.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: chain_id, - salt: 1, - offerer: 0x2284a6517b487be8114013f277f9e2010ac001a24a93e3c48cdf5f8f345a81b - .try_into() - .unwrap(), - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(10), - quantity: 1, - start_amount: 600000000000000000, - end_amount: 0, - start_date: block_timestamp, - end_date: end_date, - broker_id: 0x123.try_into().unwrap(), - additional_data: data_span, - }; - let order_hash = order_listing.compute_order_hash(); - let token_hash = order_listing.compute_token_hash(); - let sign_info = SignInfo { user_pubkey: 0, user_sig_r: 0, user_sig_s: 0, }; - (order_listing, sign_info, order_hash, token_hash) -} - -/// Utility function to setup a auction order for test environment. -/// -/// # Arguments -/// * `start_price` - The start price of the auction -/// * `end_price` - The end price of the auction -/// -/// # Returns a tuple of the different orders data -/// -fn setup_auction_order( - start_date: u64, end_date: u64, start_price: felt252, end_price: felt252, pk: Option -) -> (OrderV1, Signer, felt252, felt252) { - let offerer = 0x2284a6517b487be8114013f277f9e2010ac001a24a93e3c48cdf5f8f345a81b - .try_into() - .unwrap(); - let data = array![]; - let chain_id = 0x534e5f4d41494e; - let data_span = data.span(); - let order_listing = OrderV1 { - route: RouteType::Erc721ToErc20.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: chain_id, - salt: 1, - offerer: offerer, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(10), - quantity: 1, - start_amount: start_price.into(), - end_amount: end_price.into(), - start_date, - end_date, - broker_id: 0x123.try_into().unwrap(), - additional_data: data_span, - }; - - let order_hash = order_listing.compute_order_hash(); - let token_hash = order_listing.compute_token_hash(); - let signer = sign_mock(order_hash, offerer); - - (order_listing, signer, order_hash, token_hash) -} - -fn setup_listing( - start_date: u64, end_date: u64, token_id: Option -) -> (OrderV1, Signer, felt252, felt252) { - let data = array![]; - let data_span = data.span(); - let chain_id = 0x534e5f4d41494e; - let offerer = 0x2284a6517b487be8114013f277f9e2010ac001a24a93e3c48cdf5f8f345a81b - .try_into() - .unwrap(); - let order_listing = OrderV1 { - route: RouteType::Erc721ToErc20.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: chain_id, - salt: 1, - offerer: offerer, - token_chain_id: chain_id, - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: token_id, - quantity: 1, - start_amount: 600000000000000000, - end_amount: 0, - start_date: start_date, - end_date: end_date, - broker_id: 0x123.try_into().unwrap(), - additional_data: data_span, - }; - let order_hash = order_listing.compute_order_hash(); - let token_hash = order_listing.compute_token_hash(); - let signer = sign_mock(order_hash, offerer); - (order_listing, signer, order_hash, token_hash) -} fn get_offer_order() -> OrderV1 { let data = array![]; @@ -372,14 +195,3 @@ fn get_offer_order() -> OrderV1 { additional_data: data_span, } } - -fn whitelist_creator_broker( - contract_address: ContractAddress, broker_id: ContractAddress, dispatcher: OrderbookDispatcher -) { - start_prank( - CheatTarget::One(contract_address), - 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078.try_into().unwrap() - ); - dispatcher.whitelist_broker(broker_id); - stop_prank(CheatTarget::One(contract_address)); -} diff --git a/contracts/ark_orderbook/tests/common/signer.cairo b/contracts/ark_orderbook/tests/common/signer.cairo deleted file mode 100644 index 3ede56e94..000000000 --- a/contracts/ark_orderbook/tests/common/signer.cairo +++ /dev/null @@ -1,22 +0,0 @@ -use core::option::OptionTrait; -use ark_common::crypto::signer::{Signer, SignInfo}; -use snforge_std::signature::KeyPairTrait; -use snforge_std::signature::stark_curve::{ - StarkCurveKeyPairImpl, StarkCurveSignerImpl, StarkCurveVerifierImpl -}; - -use ark_common::crypto::typed_data::{OrderSign, TypedDataTrait}; - -fn ORDER(order_hash: felt252) -> OrderSign { - OrderSign { hash: order_hash } -} - -fn sign_mock(message_hash: felt252, signer: starknet::ContractAddress) -> Signer { - let order = ORDER(message_hash); - let order_hash = order.compute_hash_from(signer, 0x534e5f4d41494e); - let key_pair = KeyPairTrait::::generate(); - let (r, s): (felt252, felt252) = key_pair.sign(order_hash); - Signer::WEIERSTRESS_STARKNET( - SignInfo { user_pubkey: key_pair.public_key, user_sig_r: r, user_sig_s: s, } - ) -} diff --git a/contracts/ark_orderbook/tests/lib.cairo b/contracts/ark_orderbook/tests/lib.cairo index bb37b1170..411f07586 100644 --- a/contracts/ark_orderbook/tests/lib.cairo +++ b/contracts/ark_orderbook/tests/lib.cairo @@ -1,15 +1,5 @@ mod common { mod setup; - mod signer; -} - -mod integration { - mod test_create_listing_order; - mod test_create_auction_offers; - mod test_fulfill_listing; - mod test_fulfill_auction; - mod test_fulfill_offers; - mod test_cancel_order; } mod unit { diff --git a/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo b/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo index f617408ca..6a78378dc 100644 --- a/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo +++ b/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo @@ -9,7 +9,7 @@ use ark_orderbook::orderbook::{ use ark_common::protocol::order_types::{OrderType, OrderTrait, RouteType}; use ark_common::crypto::signer::{SignInfo, Signer, SignerValidator}; use debug::PrintTrait; -use super::super::super::common::setup::{setup_orders, whitelist_creator_broker}; +use super::super::super::common::setup::setup_orders; use snforge_std::{ContractClassTrait, declare}; // ********************************************************* @@ -19,8 +19,7 @@ use snforge_std::{ContractClassTrait, declare}; #[test] fn test_validate_common_data_with_valid_order() { let (order_listing, _, _, _) = setup_orders(); - let mut state = orderbook::contract_state_for_testing(); - orderbook::ImplOrderbook::whitelist_broker(ref state, order_listing.broker_id); + let block_timestmap: u64 = 1699556828; let result = order_listing.validate_common_data(starknet::get_block_timestamp()); assert(result.is_ok(), 'Invalid result'); @@ -50,9 +49,7 @@ fn should_returns_invalid_order_with_zero_salt() { #[test] fn should_returns_invalid_order_with_no_token_id() { let (order_listing, _, _, _) = setup_orders(); - - let mut state = orderbook::contract_state_for_testing(); - orderbook::ImplOrderbook::whitelist_broker(ref state, order_listing.broker_id); + let block_timestmap: u64 = 1699556828; let mut invalid_order = order_listing.clone(); invalid_order.token_id = Option::None; From a219279f05060c48797b580c79cf6837906b5efe Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Mon, 8 Jul 2024 17:47:15 +0200 Subject: [PATCH 6/9] contracts: remove obsolete test --- .../ark_orderbook/tests/unit/order/test_order_v1.cairo | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo b/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo index 6a78378dc..479bb8221 100644 --- a/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo +++ b/contracts/ark_orderbook/tests/unit/order/test_order_v1.cairo @@ -19,7 +19,6 @@ use snforge_std::{ContractClassTrait, declare}; #[test] fn test_validate_common_data_with_valid_order() { let (order_listing, _, _, _) = setup_orders(); - let block_timestmap: u64 = 1699556828; let result = order_listing.validate_common_data(starknet::get_block_timestamp()); assert(result.is_ok(), 'Invalid result'); @@ -49,7 +48,6 @@ fn should_returns_invalid_order_with_zero_salt() { #[test] fn should_returns_invalid_order_with_no_token_id() { let (order_listing, _, _, _) = setup_orders(); - let block_timestmap: u64 = 1699556828; let mut invalid_order = order_listing.clone(); invalid_order.token_id = Option::None; @@ -75,14 +73,9 @@ fn should_returns_invalid_order_with_invalid_dates() { let mut invalid_order = order_listing.clone(); invalid_order.end_date = 0; - let result = invalid_order.validate_common_data(block_timestamp); + let result = invalid_order.validate_common_data(1); assert(!result.is_ok(), 'zero end date'); - let mut invalid_order = order_listing.clone(); - invalid_order.end_date = invalid_order.start_date; - let result = invalid_order.validate_common_data(block_timestamp); - assert(!result.is_ok(), 'start date = end date'); - let mut invalid_order = order_listing.clone(); let result = invalid_order.validate_common_data(1699643230); assert(!result.is_ok(), 'past start date'); From 569e2562ea8388851cb9220d39bf395056f1460a Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Mon, 15 Jul 2024 21:30:28 +0200 Subject: [PATCH 7/9] contracts: emit `CollectionFallbackFees` when creator fees receiver is the default one. --- contracts/ark_starknet/src/executor.cairo | 23 +++++++++++++++ .../tests/integration/execute_order.cairo | 28 +++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/contracts/ark_starknet/src/executor.cairo b/contracts/ark_starknet/src/executor.cairo index ef5e970a4..54656b57c 100644 --- a/contracts/ark_starknet/src/executor.cairo +++ b/contracts/ark_starknet/src/executor.cairo @@ -110,6 +110,7 @@ mod executor { #[derive(Drop, starknet::Event)] enum Event { OrderExecuted: OrderExecuted, + CollectionFallbackFees: CollectionFallbackFees, } #[derive(Drop, starknet::Event)] @@ -121,6 +122,16 @@ mod executor { block_timestamp: u64 } + #[derive(Drop, starknet::Event)] + struct CollectionFallbackFees { + #[key] + collection: ContractAddress, + #[key] + amount: u256, + currency_contract: ContractAddress, + receiver: ContractAddress, + } + #[constructor] fn constructor( ref self: ContractState, @@ -391,6 +402,18 @@ mod executor { ); if creator_fees_amount > 0 { + let (default_receiver_creator, _) = self.get_default_creator_fees(); + if creator_address == default_receiver_creator { + self + .emit( + CollectionFallbackFees { + collection: execution_info.nft_address, + amount: creator_fees_amount, + currency_contract: currency_contract.contract_address, + receiver: default_receiver_creator, + } + ) + } currency_contract .transfer_from( execution_info.payment_from, creator_address, creator_fees_amount diff --git a/contracts/ark_starknet/tests/integration/execute_order.cairo b/contracts/ark_starknet/tests/integration/execute_order.cairo index a18152a0e..2d8f9e22f 100644 --- a/contracts/ark_starknet/tests/integration/execute_order.cairo +++ b/contracts/ark_starknet/tests/integration/execute_order.cairo @@ -14,7 +14,8 @@ use ark_tokens::erc721::IFreeMintDispatcher as Erc721Dispatcher; use ark_tokens::erc721::IFreeMintDispatcherTrait as Erc721DispatcherTrait; use snforge_std as snf; -use snf::{ContractClass, ContractClassTrait, CheatTarget}; +use snf::{cheatcodes::{events::EventFetcher, events::EventAssertions,}, event_name_hash,}; +use snf::{ContractClass, ContractClassTrait, CheatTarget, spy_events, SpyOn}; use super::super::common::setup::{setup, setup_order, setup_royalty}; @@ -188,6 +189,7 @@ fn test_execute_order_check_brokers_fees_ok() { assert_eq!(listing_broker_balance, 0, "Wrong initial balance for listing broker"); IExecutorDispatcher { contract_address: executor_address }.execute_order(execution_info); + assert_eq!(erc20.balance_of(fulfill_broker), 1_000_000, "Fulfill broker balance not correct"); assert_eq!(erc20.balance_of(listing_broker), 500_000, "Listing broker balance not correct"); } @@ -298,7 +300,10 @@ fn test_execute_order_erc2981_default_royalty_check_fees_ok() { .set_default_royalty(creator, FeesRatio { numerator: 2, denominator: 100 }); snf::stop_prank(CheatTarget::One(nft_address)); + let mut spy = spy_events(SpyOn::One(executor_address)); IExecutorDispatcher { contract_address: executor_address }.execute_order(execution_info); + spy.fetch_events(); + assert_eq!( erc20.balance_of(fulfill_broker) - fulfill_broker_balance, fulfill_broker_delta, @@ -320,6 +325,11 @@ fn test_execute_order_erc2981_default_royalty_check_fees_ok() { fulfiller_delta, "Fulfiller balance not correct" ); + + assert_eq!(spy.events.len(), 1, "Expected 1 events"); + let (_, event) = spy.events.at(0); + assert_eq!(event.keys.len(), 3, "There should be 3 keys"); + assert!(event.keys.at(0) == @event_name_hash('OrderExecuted'), "Wrong event name"); } #[test] @@ -435,7 +445,7 @@ fn test_execute_order_non_erc2981_default_royalty_check_fees_ok() { let fake_nft_address = contract_address_const::<'fake_nft_address'>(); let start_amount = 10_000_000; - let (executor_address, erc20_address, _, execution_info) = setup_execute_order( + let (executor_address, erc20_address, nft_address, execution_info) = setup_execute_order( admin_address, offerer, fulfiller, listing_broker, fulfill_broker, start_amount, false ); @@ -487,7 +497,10 @@ fn test_execute_order_non_erc2981_default_royalty_check_fees_ok() { ); snf::stop_prank(CheatTarget::One(executor.contract_address)); + let mut spy = spy_events(SpyOn::One(executor_address)); IExecutorDispatcher { contract_address: executor_address }.execute_order(execution_info); + spy.fetch_events(); + assert_eq!( erc20.balance_of(fulfill_broker) - fulfill_broker_balance, fulfill_broker_delta, @@ -509,6 +522,17 @@ fn test_execute_order_non_erc2981_default_royalty_check_fees_ok() { fulfiller_delta, "Fulfiller balance not correct" ); + + assert_eq!(spy.events.len(), 2, "Expected 2 events"); + let (_, event) = spy.events.at(0); + assert_eq!(event.keys.len(), 4, "There should be 4 keys"); + assert_eq!(@event_name_hash('CollectionFallbackFees'), event.keys.at(0), "Wrong event name"); + assert_eq!(nft_address, (*event.keys.at(1)).try_into().unwrap(), "Wrong collection address"); + assert_eq!(creator_delta.low, (*event.keys.at(2)).try_into().unwrap(), "Wrong low amount"); + assert_eq!(creator_delta.high, (*event.keys.at(3)).try_into().unwrap(), "Wrong high amount"); + let (_, event) = spy.events.at(1); + assert_eq!(event.keys.len(), 3, "There should be 3 keys"); + assert_eq!(@event_name_hash('OrderExecuted'), event.keys.at(0), "Wrong event name"); } #[test] From 7bf2a7d679bb6736d04e34d1af0b64420a6a95b3 Mon Sep 17 00:00:00 2001 From: christophe Date: Wed, 17 Jul 2024 13:18:49 +0200 Subject: [PATCH 8/9] feat(fees): update sdk & exemples for fees (#414) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description ## What type of PR is this? (check all applicable) - [ ] 🍕 Feature (`feat:`) - [ ] 🐛 Bug Fix (`fix:`) - [ ] 📝 Documentation Update (`docs:`) - [ ] 🎨 Style (`style:`) - [ ] 🧑‍💻 Code Refactor (`refactor:`) - [ ] 🔥 Performance Improvements (`perf:`) - [ ] ✅ Test (`test:`) - [ ] 🤖 Build (`build:`) - [ ] 🔁 CI (`ci:`) - [ ] 📦 Chore (`chore:`) - [ ] ⏩ Revert (`revert:`) - [ ] 🚀 Breaking Changes (`BREAKING CHANGE:`) ## Related Tickets & Documents ## Added tests? - [ ] 👍 yes - [ ] 🙅 no, because they aren't needed - [ ] 🙋 no, because I need help ## Added to documentation? - [ ] 📜 README.md - [ ] 📓 Documentation - [ ] 🙅 no documentation needed ## [optional] Are there any post-deployment tasks we need to perform? ## [optional] What gif best describes this PR or how it makes you feel? ### PR Title and Description Guidelines: - Ensure your PR title follows semantic versioning standards. This helps automate releases and changelogs. - Use types like `feat:`, `fix:`, `chore:`, `BREAKING CHANGE:` etc. in your PR title. - Your PR title will be used as a commit message when merging. Make sure it adheres to [Conventional Commits standards](https://www.conventionalcommits.org/). ## Closing Issues --- addresses.json | 1 + examples/core/cancelAuction.ts | 116 ++-- examples/core/cancelListing.ts | 116 ++-- examples/core/config/index.ts | 92 ++- examples/core/createAccount.ts | 17 - examples/core/createAuction.ts | 98 ++-- examples/core/createBroker.ts | 10 +- examples/core/createListing.ts | 112 ++-- examples/core/createOffer.ts | 118 ++-- examples/core/fulfillAuction.ts | 100 ++-- examples/core/fulfillCollectionOffer.ts | 188 +++--- examples/core/fulfillListing.ts | 162 ------ examples/core/fulfillListing2981Royalties.ts | 98 ++++ .../core/fulfillListingCollectionRoyalties.ts | 100 ++++ .../core/fulfillListingDefaultRoyalties.ts | 97 ++++ examples/core/fulfillOffer.ts | 183 +++--- examples/core/listing-process.log | 541 ++++++++++++++++++ examples/core/package.json | 3 +- examples/core/types/accounts.ts | 12 + examples/core/utils/displayBalances.ts | 22 + examples/core/utils/logger.ts | 15 + examples/core/utils/mintERC721.ts | 9 +- examples/core/utils/mintTokens.ts | 58 ++ examples/core/utils/setArkFees.ts | 5 +- .../core/utils/setCollectionCreatorFees.ts | 35 ++ examples/core/utils/setDefaultCreatorFees.ts | 33 ++ examples/core/utils/setupAccounts.ts | 69 +++ examples/core/utils/setupFees.ts | 50 ++ .../core/src/actions/broker/createBroker.ts | 24 +- .../core/src/actions/order/createListing.ts | 7 +- .../core/src/actions/order/fulfillListing.ts | 1 - packages/core/src/contracts.ts | 14 +- .../deployer/scripts/deploy-starknet-local.ts | 22 +- packages/deployer/src/contracts/erc721.ts | 8 +- .../deployer/src/contracts/erc721royalties.ts | 63 ++ pnpm-lock.yaml | 247 ++++++-- turbo.json | 2 + 37 files changed, 1988 insertions(+), 860 deletions(-) create mode 100644 addresses.json delete mode 100644 examples/core/createAccount.ts delete mode 100644 examples/core/fulfillListing.ts create mode 100644 examples/core/fulfillListing2981Royalties.ts create mode 100644 examples/core/fulfillListingCollectionRoyalties.ts create mode 100644 examples/core/fulfillListingDefaultRoyalties.ts create mode 100644 examples/core/listing-process.log create mode 100644 examples/core/types/accounts.ts create mode 100644 examples/core/utils/displayBalances.ts create mode 100644 examples/core/utils/logger.ts create mode 100644 examples/core/utils/mintTokens.ts create mode 100644 examples/core/utils/setCollectionCreatorFees.ts create mode 100644 examples/core/utils/setDefaultCreatorFees.ts create mode 100644 examples/core/utils/setupAccounts.ts create mode 100644 examples/core/utils/setupFees.ts create mode 100644 packages/deployer/src/contracts/erc721royalties.ts diff --git a/addresses.json b/addresses.json new file mode 100644 index 000000000..5a4c7b1d6 --- /dev/null +++ b/addresses.json @@ -0,0 +1 @@ +{"orderbook_address":"0x2281b4a351f12ee30f940ac2dd1e48f03b52c76c8f14169322b0f05d6a7fc32","sn_executor_address":"0x2b3a70ba9f135220d06433c4ec8a313ef8363f53e75371c222ff3895bcce7c6"} diff --git a/examples/core/cancelAuction.ts b/examples/core/cancelAuction.ts index 688471168..f7c0b6012 100644 --- a/examples/core/cancelAuction.ts +++ b/examples/core/cancelAuction.ts @@ -1,85 +1,91 @@ import "dotenv/config"; -import { stark } from "starknet"; - import { - approveERC721, AuctionV1, cancelOrder, + Config, createAuction, createBroker, - fetchOrCreateAccount, getOrderStatus } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; -import { mintERC721 } from "./utils/mintERC721.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; - -(async () => { - // Create test accounts - const adminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS_DEV, - process.env.SOLIS_ADMIN_PRIVATE_KEY_DEV - ); - const sellerAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - // Create and whitelist broker - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - await whitelistBroker(config, adminAccount, brokerId); - - // Mint and approve seller NFT - const tokenId = await getCurrentTokenId(config, nftContract); - - await mintERC721(config.starknetProvider, sellerAccount); - await approveERC721(config, { - contractAddress: nftContract, - starknetAccount: sellerAccount, - tokenId - }); - - // Create auction - const order: AuctionV1 = { - brokerId, - tokenAddress: nftContract, - tokenId, - startAmount: BigInt(1), - endAmount: BigInt(10) - }; +import { Accounts } from "./types/accounts.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; +async function createAndCancelAuctionAndCheckStatus( + config: Config, + accounts: Accounts, + tokenId: bigint, + auction: AuctionV1 +): Promise { + logger.info("Creating auction..."); const orderHash = await createAuction(config, { - starknetAccount: sellerAccount, - order, + starknetAccount: accounts.fulfiller, + order: auction, approveInfo: { tokenAddress: nftContract, tokenId } }); - // Cancel auction + logger.info("Cancelling auction..."); const cancelInfo = { orderHash: orderHash, - tokenAddress: order.tokenAddress, - tokenId: order.tokenId + tokenAddress: auction.tokenAddress, + tokenId: auction.tokenId }; - cancelOrder(config, { - starknetAccount: sellerAccount, + await cancelOrder(config, { + starknetAccount: accounts.fulfiller, cancelInfo }); await new Promise((resolve) => setTimeout(resolve, 5000)); - const { orderStatus } = await getOrderStatus(config, { - orderHash + logger.info("Fetching order status..."); + const { orderStatus } = await getOrderStatus(config, { orderHash }); + logger.info("Auction order status after cancellation:", orderStatus); +} + +async function main(): Promise { + logger.info("Starting the auction creation and cancellation process..."); + + const accounts = await setupAccounts(config); + + await createBroker(config, { + brokenAccount: accounts.broker, + numerator: 1, + denominator: 100 }); - console.log("Auction order status: ", orderStatus); -})(); + logger.info("Minting tokens..."); + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + nftContract, + true + ); + + const auction: AuctionV1 = { + brokerId: accounts.broker.address, + tokenAddress: nftContract, + tokenId, + startAmount: BigInt(orderAmount), + endAmount: BigInt(Number(orderAmount) * 2) + }; + + await createAndCancelAuctionAndCheckStatus( + config, + accounts, + tokenId, + auction + ); +} + +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/cancelListing.ts b/examples/core/cancelListing.ts index 7e91caa0e..635220a22 100644 --- a/examples/core/cancelListing.ts +++ b/examples/core/cancelListing.ts @@ -1,95 +1,93 @@ -/** - * Demonstrates how to use the Starknet SDK for creating a listing on the arkchain. - * This example shows the process of initializing a provider, creating an account, - * submitting a listing order and cancelling it. - */ - -import { stark } from "starknet"; +import "dotenv/config"; import { cancelOrder, - createAccount, + Config, createBroker, createListing, - fetchOrCreateAccount, getOrderStatus, ListingV1 } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; -import { mintERC721 } from "./utils/mintERC721.js"; - -/** - * Creates a listing on the blockchain using provided order details. - * - * @param {RpcProvider} provider - The RPC provider instance. - */ -(async () => { - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - // Create a new account using the provider - const { account: arkAccount } = await createAccount(config.arkProvider); - - const starknetOffererAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - await mintERC721(config.starknetProvider, starknetOffererAccount); - const tokenId = await getCurrentTokenId(config, nftContract); - - // Define the order details - const order: ListingV1 = { - brokerId, - tokenAddress: nftContract, // The token address - tokenId: tokenId, // The ID of the token - startAmount: BigInt(600000000000000000) // The starting amount for the order - }; - - console.log("Creating listing order..."); - // Create the listing on the arkchain using the order details +import { Accounts } from "./types/accounts.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; + +async function createAndCancelListing( + config: Config, + accounts: Accounts, + order: ListingV1 +): Promise { + logger.info("Creating listing..."); const orderHash = await createListing(config, { - starknetAccount: starknetOffererAccount, + starknetAccount: accounts.offerer, order, approveInfo: { - tokenAddress: nftContract, - tokenId + tokenAddress: order.tokenAddress, + tokenId: order.tokenId } }); - // wait 5 seconds for the transaction to be processed await new Promise((resolve) => setTimeout(resolve, 5000)); - console.log("=> Fetching order status..."); + logger.info("Fetching order status after creation..."); const { orderStatus: orderStatusBefore } = await getOrderStatus(config, { orderHash }); + logger.info("Order status before cancellation:", orderStatusBefore); - console.log("orderStatus", orderStatusBefore); - - // Define the cancel details + logger.info("Cancelling listing order..."); const cancelInfo = { orderHash: orderHash, tokenAddress: order.tokenAddress, tokenId: order.tokenId }; - console.log("Cancelling listing order..."); - // Cancel the order - cancelOrder(config, { - starknetAccount: starknetOffererAccount, + await cancelOrder(config, { + starknetAccount: accounts.offerer, cancelInfo }); - // wait 2 seconds for the transaction to be processed - await new Promise((resolve) => setTimeout(resolve, 2000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); - console.log("=> Fetching order status..."); + logger.info("Fetching order status after cancellation..."); const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { orderHash }); + logger.info("Order status after cancellation:", orderStatusAfter); + + return orderHash; +} + +async function main(): Promise { + logger.info("Starting the listing creation and cancellation process..."); + + const accounts = await setupAccounts(config); + await createBroker(config, { + brokenAccount: accounts.broker, + numerator: 1, + denominator: 100 + }); + + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + nftContract + ); + + const order: ListingV1 = { + brokerId: accounts.broker.address, + tokenAddress: nftContract, + tokenId: tokenId, + startAmount: BigInt(orderAmount) + }; + + await createAndCancelListing(config, accounts, order); +} - console.log("orderStatus", orderStatusAfter); -})(); +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/config/index.ts b/examples/core/config/index.ts index 6afb62809..22492baa0 100644 --- a/examples/core/config/index.ts +++ b/examples/core/config/index.ts @@ -3,24 +3,80 @@ import { createConfig, Network, starknetEthContract } from "@ark-project/core"; import contractsDev from "../../../contracts.dev.json"; import contractsDeployed from "../../../contracts.json"; -// Only mainnet and dev are supported for now -const network = (process.env.STARKNET_NETWORK_ID || "dev") as Network; -const isDev = network === "dev"; - -export const contracts = isDev - ? contractsDev - : network === "sepolia" - ? contractsDeployed.sepolia - : contractsDeployed.mainnet; -const starknetExecutorContract = isDev - ? contractsDev.executor - : contracts.executor; -const arkchainOrderbookContract = isDev - ? contractsDev.orderbook - : contracts.orderbook; -const starknetCurrencyContract = isDev ? contractsDev.eth : starknetEthContract; - -export const nftContract = contracts.nftContract; +// Define types for contract configurations +interface BaseContracts { + messaging: string; + executor: string; + orderbook: string; +} + +interface DevContracts extends BaseContracts { + nftContract: string; + nftContractFixedFees: string; + nftContractRoyalties: string; + eth: string; +} + +interface DeployedContracts { + sepolia: BaseContracts; + mainnet: BaseContracts; +} + +// Type guard to check if contracts object has NFT-related properties +function isDevContracts( + contracts: BaseContracts | DevContracts +): contracts is DevContracts { + return ( + "nftContract" in contracts && + "nftContractFixedFees" in contracts && + "nftContractRoyalties" in contracts && + "eth" in contracts + ); +} + +// Assert the types of imported contracts +const typedContractsDev = contractsDev as DevContracts; +const typedContractsDeployed = contractsDeployed as DeployedContracts; + +// Get the network from environment variable, defaulting to "dev" +export const network = (process.env.STARKNET_NETWORK_ID || "dev") as Network; + +// Determine if we're in development mode +export const isDev = network === "dev"; + +// Function to get the correct contract configuration based on the network +function getContractConfig(network: Network): BaseContracts | DevContracts { + switch (network) { + case "dev": + return typedContractsDev; + case "sepolia": + return typedContractsDeployed.sepolia; + case "mainnet": + return typedContractsDeployed.mainnet; + default: + throw new Error(`Unsupported network: ${network}`); + } +} + +// Get the contract configuration +export const contracts = getContractConfig(network); + +// Export specific contract addresses +export const starknetExecutorContract = contracts.executor; +export const arkchainOrderbookContract = contracts.orderbook; +export const starknetCurrencyContract = + isDev && isDevContracts(contracts) ? contracts.eth : starknetEthContract; + +// Export NFT contract addresses only if they exist +export const nftContract = isDevContracts(contracts) + ? contracts.nftContract + : undefined; +export const nftContractFixedFees = isDevContracts(contracts) + ? contracts.nftContractFixedFees + : undefined; +export const nftContractRoyalties = isDevContracts(contracts) + ? contracts.nftContractRoyalties + : undefined; export const config = createConfig({ starknetNetwork: network, diff --git a/examples/core/createAccount.ts b/examples/core/createAccount.ts deleted file mode 100644 index 4e957c422..000000000 --- a/examples/core/createAccount.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { RpcProvider } from "starknet"; - -import { createAccount } from "@ark-project/core"; - -// Initialize the RPC provider with the katana node URL for starknet -const arkProvider = new RpcProvider({ - nodeUrl: process.env.ARKCHAIN_RPC_URL ?? "http://0.0.0.0:7777" -}); - -createAccount(arkProvider).then( - ({ address, privateKey, publicKey, account }) => { - console.log("address: " + address); - console.log("privateKey: " + privateKey); - console.log("publicKey: " + publicKey); - console.log(account); - } -); diff --git a/examples/core/createAuction.ts b/examples/core/createAuction.ts index c41f573fb..3aa720678 100644 --- a/examples/core/createAuction.ts +++ b/examples/core/createAuction.ts @@ -1,65 +1,71 @@ import "dotenv/config"; -import { stark } from "starknet"; - import { - approveERC721, + AuctionV1, + Config, createAuction, createBroker, - fetchOrCreateAccount, getOrderStatus } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; -import { mintERC721 } from "./utils/mintERC721.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; - -(async () => { - // Create test accounts - const adminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS_DEV, - process.env.SOLIS_ADMIN_PRIVATE_KEY_DEV - ); - const sellerAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - // Create and whitelist broker - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - await whitelistBroker(config, adminAccount, brokerId); +import { Accounts } from "./types/accounts.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; - // Mint and approve seller NFT - const tokenId = await getCurrentTokenId(config, nftContract); - - await mintERC721(config.starknetProvider, sellerAccount); - await approveERC721(config, { - contractAddress: nftContract, - starknetAccount: sellerAccount, - tokenId - }); - - // Create auction +async function createAuctionAndCheckStatus( + config: Config, + accounts: Accounts, + tokenId: bigint, + auction: AuctionV1 +): Promise { + logger.info("Creating auction..."); const orderHash = await createAuction(config, { - starknetAccount: sellerAccount, - order: { - brokerId, - tokenAddress: nftContract, - tokenId, - startAmount: BigInt(1), - endAmount: BigInt(10) - }, + starknetAccount: accounts.fulfiller, + order: auction, approveInfo: { tokenAddress: nftContract, tokenId } }); + logger.info("Fetching order status..."); const { orderStatus } = await getOrderStatus(config, { orderHash }); + logger.info("Auction order status:", orderStatus); +} + +async function main(): Promise { + logger.info("Starting the auction creation process..."); + + const accounts = await setupAccounts(config); + + await createBroker(config, { + brokenAccount: accounts.broker, + numerator: 1, + denominator: 100 + }); + + logger.info("Minting tokens..."); + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + nftContract, + true + ); + + const auction: AuctionV1 = { + brokerId: accounts.broker.address, + tokenAddress: nftContract, + tokenId, + startAmount: BigInt(orderAmount), + endAmount: BigInt(Number(orderAmount) * 2) + }; + + await createAuctionAndCheckStatus(config, accounts, tokenId, auction); +} - console.log("Auction order status: ", orderStatus); -})(); +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/createBroker.ts b/examples/core/createBroker.ts index 00dfa8758..c42ad06e4 100644 --- a/examples/core/createBroker.ts +++ b/examples/core/createBroker.ts @@ -1,7 +1,11 @@ import { createBroker } from "@ark-project/core"; import { config } from "./config/index.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; -const brokerID = process.env.BROKER_ID as string; -console.log("Creating broker with ID: " + brokerID); -createBroker(config, { brokerID }); +const accounts = await setupAccounts(config); +await createBroker(config, { + brokenAccount: accounts.broker, + numerator: 1, + denominator: 100 +}); diff --git a/examples/core/createListing.ts b/examples/core/createListing.ts index d9818ddf3..ede53e803 100644 --- a/examples/core/createListing.ts +++ b/examples/core/createListing.ts @@ -1,85 +1,77 @@ -/** - * Demonstrates how to use the Starknet SDK for creating a listing on the arkchain. - * This example shows the process of initializing a provider, creating an account, - * submitting a listing order. - * checking the order status - */ - import "dotenv/config"; -import { stark } from "starknet"; - import { + Config, createBroker, createListing, - fetchOrCreateAccount, getOrderStatus, ListingV1 } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; +import { Accounts } from "./types/accounts.js"; import { getTokenOwner } from "./utils/getTokenOwner.js"; -import { mintERC721 } from "./utils/mintERC721.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; + +async function createListingAndCheckStatus( + config: Config, + accounts: Accounts, + order: ListingV1 +): Promise { + logger.info("Creating listing..."); + const orderHash = await createListing(config, { + starknetAccount: accounts.offerer, + order, + approveInfo: { + tokenAddress: order.tokenAddress, + tokenId: order.tokenId + } + }); + logger.info("Order hash:", orderHash); -/** - * Creates a listing on the blockchain using provided order details. - */ -(async () => { - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); + await new Promise((resolve) => setTimeout(resolve, 2000)); - const solisAdminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS_DEV, - process.env.SOLIS_ADMIN_PRIVATE_KEY_DEV - ); + logger.info("Fetching order status..."); + const { orderStatus } = await getOrderStatus(config, { orderHash }); + logger.info("Order status:", orderStatus); - console.log(`=> Whitelisting broker ${brokerId}`); - await whitelistBroker(config, solisAdminAccount, brokerId); + return orderHash; +} - console.log( - `=> Fetching or creating offerer starknet account, for test purpose only` - ); +async function main(): Promise { + logger.info("Starting the listing creation and status check process..."); - const starknetOffererAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY + const accounts = await setupAccounts(config); + + await createBroker(config, { + brokenAccount: accounts.broker, + numerator: 1, + denominator: 100 + }); + + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + nftContract ); - console.log("=> Minting token at contract address: ", nftContract); - await mintERC721(config.starknetProvider, starknetOffererAccount); - const tokenId = await getCurrentTokenId(config, nftContract); const owner = await getTokenOwner(config, nftContract, tokenId); const ownerHex = "0x" + owner.toString(16).padStart(64, "0"); - console.log("Owner of tokenId", tokenId, "is", ownerHex); + logger.info(`Owner of tokenId ${tokenId} is ${ownerHex}`); - console.log(`=> Creating order`); - // Define the order details const order: ListingV1 = { - brokerId, // The broker ID - tokenAddress: nftContract, // The token address - tokenId: tokenId, // The ID of the token - startAmount: BigInt(100000000000000000) // The starting amount for the order + brokerId: accounts.broker.address, + tokenAddress: nftContract, + tokenId: tokenId, + startAmount: BigInt(orderAmount) }; - console.log("=> Creating listing..."); - // Create the listing on the arkchain using the order details - const orderHash = await createListing(config, { - starknetAccount: starknetOffererAccount, - order, - approveInfo: { - tokenAddress: order.tokenAddress, - tokenId: order.tokenId - } - }); - console.log("orderHash", orderHash); - console.log("=> Fetching order status..."); - const { orderStatus } = await getOrderStatus(config, { - orderHash - }); + await createListingAndCheckStatus(config, accounts, order); +} - console.log("orderStatus", orderStatus); -})(); +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/createOffer.ts b/examples/core/createOffer.ts index 51595949c..26cc97eb8 100644 --- a/examples/core/createOffer.ts +++ b/examples/core/createOffer.ts @@ -1,15 +1,9 @@ -/** - * Demonstrates how to use the Starknet SDK for creating a offer on the arkchain. - * This example shows the process of initializing a provider, creating an account, - * submitting a offer order - * checking the order status - */ - import "dotenv/config"; -import { stark } from "starknet"; +import * as sn from "starknet"; import { + Config, createBroker, createOffer, fetchOrCreateAccount, @@ -18,73 +12,63 @@ import { } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { mintERC20 } from "./utils/mintERC20.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; - -/** - * Creates a offer on the blockchain using provided order details. - */ -(async () => { - console.log(`=> Getting config...`); - const { starknetProvider } = config; - - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - - console.log(`=> Creating account`); - // Create a new account for the offer using the provider - const solisAdminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS_DEV, - process.env.SOLIS_ADMIN_PRIVATE_KEY_DEV - ); - - console.log(`=> Whitelisting broker ${brokerId}`); - await whitelistBroker(config, solisAdminAccount, brokerId); - - console.log( - `=> Fetching or creating offerer starknet account, for test purpose only` - ); - const starknetOffererAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - console.log(`=> Creating order`); - // Define the offer details - const offer: OfferV1 = { - brokerId, // The broker ID - tokenAddress: nftContract, // The token address - tokenId: BigInt(20), // The ID of the token - startAmount: BigInt(100000000000000000), // The starting amount for the order - currencyAddress: config.starknetCurrencyContract // The ERC20 address - }; - - if (process.env.STARKNET_NETWORK_ID === "dev") { - console.log("=> Minting ERC20..."); - await mintERC20( - starknetProvider, - starknetOffererAccount, - offer.startAmount - ); - } +import { Accounts } from "./types/accounts.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; - console.log("=> Creating Offer..."); - // Create the offer on the arkchain using the order details +async function createOfferAndCheckStatus( + config: Config, + accounts: Accounts, + offer: OfferV1 +): Promise { + logger.info("Creating offer..."); const orderHash = await createOffer(config, { - starknetAccount: starknetOffererAccount, + starknetAccount: accounts.offerer, offer, approveInfo: { currencyAddress: config.starknetCurrencyContract, amount: offer.startAmount } }); + logger.info("Order hash:", orderHash); - console.log("=> Fetching order status..."); - const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { - orderHash + await new Promise((resolve) => setTimeout(resolve, 5000)); + + logger.info("Fetching order status..."); + const { orderStatus } = await getOrderStatus(config, { orderHash }); + logger.info("Order status:", orderStatus); + + return orderHash; +} + +async function main(): Promise { + logger.info("Starting the offer creation and status check process..."); + + const accounts = await setupAccounts(config); + + const brokerId = sn.stark.randomAddress(); + await createBroker(config, { + brokenAccount: accounts.broker, + numerator: 1, + denominator: 100 }); - console.log("orderStatus", orderStatusAfter); -})(); + logger.info("Minting tokens..."); + const { orderAmount } = await mintTokens(config, accounts, nftContract, true); + + const offer: OfferV1 = { + brokerId: accounts.broker.address, + tokenAddress: nftContract, + tokenId: BigInt(20), // Note: This is hardcoded, you might want to generate this dynamically + startAmount: orderAmount, + currencyAddress: config.starknetCurrencyContract + }; + + await createOfferAndCheckStatus(config, accounts, offer); +} + +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/fulfillAuction.ts b/examples/core/fulfillAuction.ts index d792d35df..fb51060fa 100644 --- a/examples/core/fulfillAuction.ts +++ b/examples/core/fulfillAuction.ts @@ -1,13 +1,13 @@ import "dotenv/config"; -import { stark } from "starknet"; +import * as sn from "starknet"; import { AuctionV1, + Config, createAuction, createBroker, createOffer, - fetchOrCreateAccount, fulfillAuction, FulfillAuctionInfo, getOrderStatus, @@ -15,41 +15,20 @@ import { } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; -import { mintERC721 } from "./utils/mintERC721.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; - -(async () => { - // Create test accounts - const adminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS, - process.env.SOLIS_ADMIN_PRIVATE_KEY - ); - - const sellerAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - const buyerAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT2_ADDRESS, - process.env.STARKNET_ACCOUNT2_PRIVATE_KEY - ); - - // Create and whitelist broker - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - await whitelistBroker(config, adminAccount, brokerId); - - // Mint and approve seller NFT - await mintERC721(config.starknetProvider, sellerAccount); - const tokenId = await getCurrentTokenId(config, nftContract); +import { Accounts } from "./types/accounts.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; + +async function createAndFulfillAuction( + config: Config, + accounts: Accounts, + tokenId: bigint +): Promise { + const brokerId = accounts.broker.address; // Create auction - const order: AuctionV1 = { + const auction: AuctionV1 = { brokerId, tokenAddress: nftContract, tokenId, @@ -57,10 +36,10 @@ import { whitelistBroker } from "./utils/whitelistBroker.js"; endAmount: BigInt(10) }; - console.log("Creating auction..."); - const orderHash = await createAuction(config, { - starknetAccount: sellerAccount, - order, + logger.info("Creating auction..."); + const auctionOrderHash = await createAuction(config, { + starknetAccount: accounts.fulfiller, + order: auction, approveInfo: { tokenAddress: nftContract, tokenId @@ -77,9 +56,9 @@ import { whitelistBroker } from "./utils/whitelistBroker.js"; startAmount: BigInt(1) }; - console.log("Creating offer..."); + logger.info("Creating offer..."); const offerOrderHash = await createOffer(config, { - starknetAccount: buyerAccount, + starknetAccount: accounts.offerer, offer, approveInfo: { currencyAddress: config.starknetCurrencyContract, @@ -91,24 +70,47 @@ import { whitelistBroker } from "./utils/whitelistBroker.js"; // Fulfill auction const fulfillAuctionInfo: FulfillAuctionInfo = { - orderHash, + orderHash: auctionOrderHash, relatedOrderHash: offerOrderHash, - tokenAddress: order.tokenAddress, + tokenAddress: auction.tokenAddress, tokenId, brokerId }; - console.log("Fulfilling auction..."); + logger.info("Fulfilling auction..."); await fulfillAuction(config, { - starknetAccount: sellerAccount, + starknetAccount: accounts.fulfiller, fulfillAuctionInfo }); await new Promise((resolve) => setTimeout(resolve, 5000)); - const { orderStatus: orderStatus } = await getOrderStatus(config, { - orderHash + const { orderStatus } = await getOrderStatus(config, { + orderHash: auctionOrderHash }); + logger.info("Auction order status:", orderStatus); +} + +async function main(): Promise { + logger.info( + "Starting the auction creation, offer, and fulfillment process..." + ); + + const accounts = await setupAccounts(config); + + await createBroker(config, { + brokenAccount: accounts.broker, + numerator: 1, + denominator: 100 + }); + + logger.info("Minting tokens..."); + const { tokenId } = await mintTokens(config, accounts, nftContract, true); + + await createAndFulfillAuction(config, accounts, tokenId); +} - console.log("Auction order status: ", orderStatus); -})(); +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/fulfillCollectionOffer.ts b/examples/core/fulfillCollectionOffer.ts index 443e6a97c..54ac1c4b9 100644 --- a/examples/core/fulfillCollectionOffer.ts +++ b/examples/core/fulfillCollectionOffer.ts @@ -1,158 +1,110 @@ -/** - * Demonstrates how to use the Starknet SDK for creating a listing on the arkchain. - * This example shows the process of initializing a provider, creating an account, - * submitting a listing order and cancelling it. - */ - -import { stark } from "starknet"; - import "dotenv/config"; import { - approveERC20, - approveERC721, - createAccount, - createBroker, + Config, createOffer, - fetchOrCreateAccount, fulfillOffer, getOrderStatus, OfferV1 } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; -import { mintERC20 } from "./utils/mintERC20.js"; -import { mintERC721 } from "./utils/mintERC721.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; - -/** - * Creates a listing on the blockchain using provided order details. - */ -(async () => { - console.log(`=> Getting config...`); - const { arkProvider, starknetProvider } = config; - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - - const solisAdminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS_DEV, - process.env.SOLIS_ADMIN_PRIVATE_KEY_DEV - ); - - await whitelistBroker(config, solisAdminAccount, brokerId); - - console.log(`=> Creating account`); - // Create a new account for the listing using the provider - const { account: arkAccount } = await createAccount(arkProvider); - - console.log( - `=> Fetching or creating fulfiller starknet account, for test purpose only` - ); - const starknetFulfillerAccount = await fetchOrCreateAccount( - starknetProvider, - process.env.STARKNET_ACCOUNT2_ADDRESS, - process.env.STARKNET_ACCOUNT2_PRIVATE_KEY - ); - - console.log( - `=> Minting token at contract address: ${nftContract} with fulfiller account: ${starknetFulfillerAccount.address}` - ); - await mintERC721(starknetProvider, starknetFulfillerAccount); - if (config.starknetNetwork !== "dev") { - console.log("=> Waiting for 5 minutes for transaction complete..."); - await new Promise((resolve) => setTimeout(resolve, 5 * 60 * 1000)); - } - - const tokenId = await getCurrentTokenId(config, nftContract); - console.log("=> Token minted with tokenId: ", tokenId); - - console.log(`=> Creating offer for tokenId: ${tokenId}`); - // Define the order details - const offer: OfferV1 = { - brokerId, // The broker ID - tokenAddress: nftContract, // The token address - tokenId: tokenId, // The ID of the token - startAmount: BigInt(100000000000000000) // The starting amount for the order - }; - - console.log( - `=> Fetching or creating offerer starknet account, for test purpose only` - ); - const starknetOffererAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - if (process.env.STARKNET_NETWORK_ID === "dev") { - console.log("=> Minting ERC20..."); - await mintERC20( - starknetProvider, - starknetOffererAccount, - offer.startAmount - ); - } - - console.log( - `=> Approuving ERC20 tokens ${config.starknetCurrencyContract} from minter: ${starknetOffererAccount.address} to ArkProject executor` - ); - await approveERC20(config, { - starknetAccount: starknetOffererAccount, - contractAddress: config.starknetCurrencyContract, - amount: offer.startAmount - }); - - console.log("=> Creating offer..."); - // Create the listing on the arkchain using the order details +import { Accounts } from "./types/accounts.js"; +import { displayBalances } from "./utils/displayBalances.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; +import { setupFees } from "./utils/setupFees.js"; + +async function createAndFulfillCollectionOffer( + config: Config, + accounts: Accounts, + offer: OfferV1 +): Promise { + logger.info("Creating collection offer..."); const orderHash = await createOffer(config, { - starknetAccount: starknetOffererAccount, + starknetAccount: accounts.offerer, offer, approveInfo: { currencyAddress: config.starknetCurrencyContract, amount: offer.startAmount } }); - console.log(`Order hash: ${orderHash}`); - - console.log(`=> Approving collection ${offer.tokenId}`); - await approveERC721(config, { - contractAddress: nftContract, - starknetAccount: starknetFulfillerAccount, - tokenId - }); if (config.starknetNetwork !== "dev") { - console.log("=> Waiting for 5 minutes for transaction complete..."); - await new Promise((resolve) => setTimeout(resolve, 5 * 60 * 1000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); } - // Define the fulfill details + logger.info("Fulfilling collection offer..."); const fulfillOfferInfo = { orderHash: orderHash, tokenAddress: offer.tokenAddress, tokenId: offer.tokenId, - brokerId + brokerId: offer.brokerId }; - console.log(`=> Fulfilling offer by ${starknetFulfillerAccount.address}`); - // fulfill the order await fulfillOffer(config, { - starknetAccount: starknetFulfillerAccount, + starknetAccount: accounts.fulfiller, fulfillOfferInfo, approveInfo: { tokenAddress: nftContract, - tokenId: tokenId + tokenId: offer.tokenId } }); + logger.info("Collection offer created and fulfilled."); + return orderHash; +} + +async function main(): Promise { + logger.info( + "Starting the collection offer creation and fulfillment process..." + ); + + const accounts = await setupAccounts(config); + await setupFees(config, accounts); + + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + nftContract, + true + ); + + const offer: OfferV1 = { + brokerId: accounts.broker.address, + tokenAddress: nftContract, + tokenId: tokenId, + startAmount: orderAmount + }; + + await displayBalances( + config, + accounts, + "before collection offer creation and fulfillment" + ); + + const orderHash = await createAndFulfillCollectionOffer( + config, + accounts, + offer + ); + await new Promise((resolve) => setTimeout(resolve, 5000)); - console.log("=> Fetching order status..."); const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { orderHash }); + logger.info("Order status after fulfillment:", orderStatusAfter); + + await displayBalances( + config, + accounts, + "after collection offer creation and fulfillment" + ); +} - console.log("orderStatus", orderStatusAfter); -})(); +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/fulfillListing.ts b/examples/core/fulfillListing.ts deleted file mode 100644 index e0f0cb3ce..000000000 --- a/examples/core/fulfillListing.ts +++ /dev/null @@ -1,162 +0,0 @@ -/** - * Demonstrates how to use the Starknet SDK for creating a listing on the arkchain. - * This example shows the process of initializing a provider, creating an account, - * submitting a listing order and cancelling it. - */ - -import "dotenv/config"; - -import { stark } from "starknet"; - -import { - approveERC20, - approveERC721, - createBroker, - createListing, - fetchOrCreateAccount, - fulfillListing, - getOrderStatus, - ListingV1 -} from "@ark-project/core"; - -import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; -import { mintERC20 } from "./utils/mintERC20.js"; -import { mintERC721 } from "./utils/mintERC721.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; - -/** - * Creates a listing on the blockchain using provided order details. - */ -(async () => { - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - - const solisAdminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS_DEV, - process.env.SOLIS_ADMIN_PRIVATE_KEY_DEV - ); - - console.log(`=> Whitelisting broker ${brokerId}`); - await whitelistBroker(config, solisAdminAccount, brokerId); - - console.log(`=> Getting config...`); - const { starknetProvider } = config; - - console.log( - `=> Fetching or creating offerer starknet account, for test purpose only` - ); - const starknetOffererAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - console.log("=> Minting token at contract address: ", nftContract); - const transaction_hash = await mintERC721( - starknetProvider, - starknetOffererAccount - ); - - console.log(transaction_hash); - - if (config.starknetNetwork !== "dev") { - console.log("=> Waiting for 5 minutes for transaction complete..."); - await new Promise((resolve) => setTimeout(resolve, 5 * 60 * 1000)); - } - - const tokenId = await getCurrentTokenId(config, nftContract); - console.log("=> Token minted with tokenId: ", tokenId); - - console.log(`=> Approving for all`); - await approveERC721(config, { - contractAddress: nftContract, - starknetAccount: starknetOffererAccount, - tokenId - }); - - console.log(`=> Creating order`); - // Define the order details - const order: ListingV1 = { - brokerId, // The broker ID - tokenAddress: nftContract, // The token address - tokenId: tokenId, // The ID of the token - startAmount: BigInt(100000000000000000) // The starting amount for the order - }; - - console.log("=> Creating listing..."); - // Create the listing on the arkchain using the order details - const orderHash = await createListing(config, { - starknetAccount: starknetOffererAccount, - order, - approveInfo: { - tokenAddress: nftContract, - tokenId - } - }); - - if (config.starknetNetwork !== "dev") { - await new Promise((resolve) => setTimeout(resolve, 5000)); - } - console.log( - `=> Fetching or creating fulfiller starknet account, for test purpose only` - ); - const starknetFulfillerAccount = await fetchOrCreateAccount( - starknetProvider, - process.env.STARKNET_ACCOUNT2_ADDRESS, - process.env.STARKNET_ACCOUNT2_PRIVATE_KEY - ); - - if (process.env.STARKNET_NETWORK_ID === "dev") { - console.log("=> Minting ERC20..."); - await mintERC20( - starknetProvider, - starknetFulfillerAccount, - order.startAmount - ); - } - - console.log( - `=> Approving ERC20 tokens ${config.starknetCurrencyContract} from minter: ${starknetFulfillerAccount.address} to ArkProject executor` - ); - - await approveERC20(config, { - starknetAccount: starknetFulfillerAccount, - contractAddress: config.starknetCurrencyContract, - amount: order.startAmount - }); - - if (config.starknetNetwork !== "dev") { - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - console.log("tokenId", tokenId); - console.log("orderHash", orderHash); - // Define the fulfill details - const fulfillListingInfo = { - orderHash: orderHash, - tokenAddress: order.tokenAddress, - tokenId, - brokerId - }; - - console.log(`=> Fulfilling listing by ${starknetFulfillerAccount.address}`); - // fulfill the order - await fulfillListing(config, { - starknetAccount: starknetFulfillerAccount, - fulfillListingInfo, - approveInfo: { - currencyAddress: config.starknetCurrencyContract, - amount: order.startAmount - } - }); - - await new Promise((resolve) => setTimeout(resolve, 5000)); - - console.log("=> Fetching order status..."); - const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { - orderHash - }); - - console.log("orderStatus", orderStatusAfter); -})(); diff --git a/examples/core/fulfillListing2981Royalties.ts b/examples/core/fulfillListing2981Royalties.ts new file mode 100644 index 000000000..9bf8ef748 --- /dev/null +++ b/examples/core/fulfillListing2981Royalties.ts @@ -0,0 +1,98 @@ +import "dotenv/config"; + +import { + Config, + createListing, + fulfillListing, + getOrderStatus, + ListingV1 +} from "@ark-project/core"; + +import { config, contracts, isDev } from "./config/index.js"; +import { Accounts } from "./types/accounts.js"; +import { displayBalances } from "./utils/displayBalances.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; +import { setupFees } from "./utils/setupFees.js"; + +async function createAndFulfillListing( + config: Config, + accounts: Accounts, + order: ListingV1 +): Promise { + logger.info("Creating listing..."); + const orderHash = await createListing(config, { + starknetAccount: accounts.offerer, + order, + approveInfo: { + tokenAddress: order.tokenAddress, + tokenId: order.tokenId + } + }); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + + logger.info("Fulfilling listing..."); + const fulfillListingInfo = { + orderHash: orderHash, + tokenAddress: order.tokenAddress, + tokenId: order.tokenId, + brokerId: accounts.broker_sale.address + }; + + await fulfillListing(config, { + starknetAccount: accounts.fulfiller, + fulfillListingInfo, + approveInfo: { + currencyAddress: config.starknetCurrencyContract, + amount: order.startAmount + } + }); + + logger.info("Listing created and fulfilled."); + return orderHash; +} + +async function main(): Promise { + if (!isDev || !("nftContract" in contracts)) { + throw new Error("NFT contract is not available in this environment"); + } + + logger.info("Starting the listing process..."); + + const accounts = await setupAccounts(config); + await setupFees(config, accounts); + + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + contracts.nftContractRoyalties + ); + + const order: ListingV1 = { + brokerId: accounts.broker_listing.address, + tokenAddress: contracts.nftContractRoyalties, + tokenId: tokenId, + startAmount: BigInt(orderAmount) + }; + + await displayBalances(config, accounts, "before sale"); + + const orderHash = await createAndFulfillListing(config, accounts, order); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + + const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { + orderHash + }); + + logger.info("Order status after fulfillment:", orderStatusAfter); + + await displayBalances(config, accounts, "after sale"); +} + +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/fulfillListingCollectionRoyalties.ts b/examples/core/fulfillListingCollectionRoyalties.ts new file mode 100644 index 000000000..9c13a89d7 --- /dev/null +++ b/examples/core/fulfillListingCollectionRoyalties.ts @@ -0,0 +1,100 @@ +import "dotenv/config"; + +import { log } from "winston"; + +import { + Config, + createListing, + fulfillListing, + getOrderStatus, + ListingV1 +} from "@ark-project/core"; + +import { config, contracts, isDev } from "./config/index.js"; +import { Accounts } from "./types/accounts.js"; +import { displayBalances } from "./utils/displayBalances.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; +import { setupFees } from "./utils/setupFees.js"; + +async function createAndFulfillListing( + config: Config, + accounts: Accounts, + order: ListingV1 +): Promise { + logger.info("Creating listing..."); + const orderHash = await createListing(config, { + starknetAccount: accounts.offerer, + order, + approveInfo: { + tokenAddress: order.tokenAddress, + tokenId: order.tokenId + } + }); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + + logger.info("Fulfilling listing..."); + const fulfillListingInfo = { + orderHash: orderHash, + tokenAddress: order.tokenAddress, + tokenId: order.tokenId, + brokerId: accounts.broker_sale.address + }; + + await fulfillListing(config, { + starknetAccount: accounts.fulfiller, + fulfillListingInfo, + approveInfo: { + currencyAddress: config.starknetCurrencyContract, + amount: order.startAmount + } + }); + + logger.info("Listing created and fulfilled."); + return orderHash; +} + +async function main(): Promise { + if (!isDev || !("nftContract" in contracts)) { + throw new Error("NFT contract is not available in this environment"); + } + + logger.info("Starting the listing process..."); + + const accounts = await setupAccounts(config); + await setupFees(config, accounts); + + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + contracts.nftContractFixedFees + ); + + const order: ListingV1 = { + brokerId: accounts.broker_listing.address, + tokenAddress: contracts.nftContractFixedFees, + tokenId: tokenId, + startAmount: BigInt(orderAmount) + }; + + await displayBalances(config, accounts, "before sale"); + + const orderHash = await createAndFulfillListing(config, accounts, order); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + + const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { + orderHash + }); + + logger.info("Order status after fulfillment:", orderStatusAfter); + + await displayBalances(config, accounts, "after sale"); +} + +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/fulfillListingDefaultRoyalties.ts b/examples/core/fulfillListingDefaultRoyalties.ts new file mode 100644 index 000000000..bcea75fa3 --- /dev/null +++ b/examples/core/fulfillListingDefaultRoyalties.ts @@ -0,0 +1,97 @@ +import "dotenv/config"; + +import { + Config, + createListing, + fulfillListing, + getOrderStatus, + ListingV1 +} from "@ark-project/core"; + +import { config, contracts, isDev } from "./config/index.js"; +import { Accounts } from "./types/accounts.js"; +import { displayBalances } from "./utils/displayBalances.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; +import { setupFees } from "./utils/setupFees.js"; + +async function createAndFulfillListing( + config: Config, + accounts: Accounts, + order: ListingV1 +): Promise { + logger.info("Creating listing..."); + const orderHash = await createListing(config, { + starknetAccount: accounts.offerer, + order, + approveInfo: { + tokenAddress: order.tokenAddress, + tokenId: order.tokenId + } + }); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + + logger.info("Fulfilling listing..."); + const fulfillListingInfo = { + orderHash: orderHash, + tokenAddress: order.tokenAddress, + tokenId: order.tokenId, + brokerId: accounts.broker_sale.address + }; + + await fulfillListing(config, { + starknetAccount: accounts.fulfiller, + fulfillListingInfo, + approveInfo: { + currencyAddress: config.starknetCurrencyContract, + amount: order.startAmount + } + }); + + logger.info("Listing created and fulfilled."); + return orderHash; +} + +async function main(): Promise { + if (!isDev || !("nftContract" in contracts)) { + throw new Error("NFT contract is not available in this environment"); + } + logger.info("Starting the listing process..."); + + const accounts = await setupAccounts(config); + await setupFees(config, accounts); + + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + contracts.nftContract + ); + + const order: ListingV1 = { + brokerId: accounts.broker_listing.address, + tokenAddress: contracts.nftContract, + tokenId: tokenId, + startAmount: BigInt(orderAmount) + }; + + await displayBalances(config, accounts, "before sale"); + + const orderHash = await createAndFulfillListing(config, accounts, order); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + + const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { + orderHash + }); + + logger.info("Order status after fulfillment:", orderStatusAfter); + + await displayBalances(config, accounts, "after sale"); +} + +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/fulfillOffer.ts b/examples/core/fulfillOffer.ts index 3e2f7cd5b..b0383f7e6 100644 --- a/examples/core/fulfillOffer.ts +++ b/examples/core/fulfillOffer.ts @@ -1,113 +1,31 @@ -/** - * Demonstrates how to use the Starknet SDK for creating a listing on the arkchain. - * This example shows the process of initializing a provider, creating an account, - * submitting a listing order and cancelling it. - */ - -import { stark } from "starknet"; - import "dotenv/config"; +import * as sn from "starknet"; + import { - approveERC20, - approveERC721, - createAccount, - createBroker, + Config, createOffer, - fetchOrCreateAccount, fulfillOffer, getOrderStatus, OfferV1 } from "@ark-project/core"; import { config, nftContract } from "./config/index.js"; -import { getCurrentTokenId } from "./utils/getCurrentTokenId.js"; -import { mintERC20 } from "./utils/mintERC20.js"; -import { mintERC721 } from "./utils/mintERC721.js"; -import { whitelistBroker } from "./utils/whitelistBroker.js"; - -/** - * Creates a listing on the blockchain using provided order details. - */ -(async () => { - console.log(`=> Getting config...`); - const { arkProvider, starknetProvider } = config; - const brokerId = stark.randomAddress(); - await createBroker(config, { brokerID: brokerId }); - - const solisAdminAccount = await fetchOrCreateAccount( - config.arkProvider, - process.env.SOLIS_ADMIN_ADDRESS_DEV, - process.env.SOLIS_ADMIN_PRIVATE_KEY_DEV - ); - - await whitelistBroker(config, solisAdminAccount, brokerId); - - console.log(`=> Creating account`); - // Create a new account for the listing using the provider - const { account: arkAccount } = await createAccount(arkProvider); - - console.log( - `=> Fetching or creating fulfiller starknet account, for test purpose only` - ); - const starknetFulfillerAccount = await fetchOrCreateAccount( - starknetProvider, - process.env.STARKNET_ACCOUNT2_ADDRESS, - process.env.STARKNET_ACCOUNT2_PRIVATE_KEY - ); - - console.log( - `=> Minting token at contract address: ${nftContract} with fulfiller account: ${starknetFulfillerAccount.address}` - ); - await mintERC721(starknetProvider, starknetFulfillerAccount); - if (config.starknetNetwork !== "dev") { - console.log("=> Waiting for 5 minutes for transaction complete..."); - await new Promise((resolve) => setTimeout(resolve, 5 * 60 * 1000)); - } - - const tokenId = await getCurrentTokenId(config, nftContract); - console.log("=> Token minted with tokenId: ", tokenId); - - console.log(`=> Creating offer for tokenId: ${tokenId}`); - // Define the order details - const offer: OfferV1 = { - brokerId, // The broker ID - tokenAddress: nftContract, // The token address - tokenId: tokenId, // The ID of the token - startAmount: BigInt(100000000000000000) // The starting amount for the order - }; - - console.log( - `=> Fetching or creating offerer starknet account, for test purpose only` - ); - const starknetOffererAccount = await fetchOrCreateAccount( - config.starknetProvider, - process.env.STARKNET_ACCOUNT1_ADDRESS, - process.env.STARKNET_ACCOUNT1_PRIVATE_KEY - ); - - if (process.env.STARKNET_NETWORK_ID === "dev") { - console.log("=> Minting ERC20..."); - await mintERC20( - starknetProvider, - starknetOffererAccount, - offer.startAmount - ); - } - - console.log( - `=> Approuving ERC20 tokens ${config.starknetCurrencyContract} from minter: ${starknetOffererAccount.address} to ArkProject executor` - ); - await approveERC20(config, { - starknetAccount: starknetOffererAccount, - contractAddress: config.starknetCurrencyContract, - amount: offer.startAmount - }); - - console.log("=> Creating offer..."); - // Create the listing on the arkchain using the order details +import { Accounts } from "./types/accounts.js"; +import { displayBalances } from "./utils/displayBalances.js"; +import { logger } from "./utils/logger.js"; +import { mintTokens } from "./utils/mintTokens.js"; +import { setupAccounts } from "./utils/setupAccounts.js"; +import { setupFees } from "./utils/setupFees.js"; + +async function createAndFulfillOffer( + config: Config, + accounts: Accounts, + offer: OfferV1 +): Promise { + logger.info("Creating offer..."); const orderHash = await createOffer(config, { - starknetAccount: starknetOffererAccount, + starknetAccount: accounts.offerer, offer, approveInfo: { currencyAddress: config.starknetCurrencyContract, @@ -115,43 +33,74 @@ import { whitelistBroker } from "./utils/whitelistBroker.js"; } }); - console.log(`=> Approving collection ${offer.tokenId}`); - await approveERC721(config, { - contractAddress: nftContract, - starknetAccount: starknetFulfillerAccount, - tokenId - }); - if (config.starknetNetwork !== "dev") { - console.log("=> Waiting for 5 minutes for transaction complete..."); - await new Promise((resolve) => setTimeout(resolve, 5 * 60 * 1000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); } - // Define the fulfill details + logger.info("Fulfilling offer..."); const fulfillOfferInfo = { orderHash: orderHash, tokenAddress: offer.tokenAddress, tokenId: offer.tokenId, - brokerId + brokerId: offer.brokerId }; - console.log(`=> Fulfilling offer by ${starknetFulfillerAccount.address}`); - // fulfill the order await fulfillOffer(config, { - starknetAccount: starknetFulfillerAccount, + starknetAccount: accounts.fulfiller, fulfillOfferInfo, approveInfo: { tokenAddress: nftContract, - tokenId: tokenId + tokenId: offer.tokenId } }); + logger.info("Offer created and fulfilled."); + return orderHash; +} + +async function main(): Promise { + logger.info("Starting the offer creation and fulfillment process..."); + + const accounts = await setupAccounts(config); + await setupFees(config, accounts); + + const { tokenId, orderAmount } = await mintTokens( + config, + accounts, + nftContract, + true + ); + + const offer: OfferV1 = { + brokerId: accounts.broker.address, + tokenAddress: nftContract, + tokenId: tokenId, + startAmount: orderAmount + }; + + await displayBalances( + config, + accounts, + "before offer creation and fulfillment" + ); + + const orderHash = await createAndFulfillOffer(config, accounts, offer); + await new Promise((resolve) => setTimeout(resolve, 5000)); - console.log("=> Fetching order status..."); const { orderStatus: orderStatusAfter } = await getOrderStatus(config, { orderHash }); + logger.info("Order status after fulfillment:", orderStatusAfter); + + await displayBalances( + config, + accounts, + "after offer creation and fulfillment" + ); +} - console.log("orderStatus", orderStatusAfter); -})(); +main().catch((error) => { + logger.error("An error occurred:", error); + process.exit(1); +}); diff --git a/examples/core/listing-process.log b/examples/core/listing-process.log new file mode 100644 index 000000000..ade7c1ce7 --- /dev/null +++ b/examples/core/listing-process.log @@ -0,0 +1,541 @@ +2024-07-15T17:32:23.594Z [INFO]: Starting the listing process... +2024-07-15T17:32:23.595Z [INFO]: Setting up accounts... +2024-07-15T17:32:23.596Z [INFO]: Accounts setup complete. +2024-07-15T17:32:23.596Z [INFO]: Setting up fees... +2024-07-15T17:32:53.907Z [INFO]: Fees setup complete. +2024-07-15T17:32:53.908Z [INFO]: Minting and approving tokens... +2024-07-15T17:32:55.997Z [INFO]: ERC721 minting transaction hash: +2024-07-15T17:32:56.026Z [INFO]: Token minted with tokenId: +2024-07-15T17:32:56.027Z [INFO]: Minting ERC20... +2024-07-15T17:32:58.099Z [INFO]: Token minting complete. +2024-07-15T17:32:58.100Z [INFO]: Displaying balances before sale: +2024-07-15T17:32:58.117Z [INFO]: arkReceiver balance: 0 +2024-07-15T17:32:58.129Z [INFO]: admin balance: 892000000000000000 +2024-07-15T17:32:58.138Z [INFO]: broker balance: 8000000000000000 +2024-07-15T17:32:58.147Z [INFO]: offerer balance: 892000000000000000 +2024-07-15T17:32:58.154Z [INFO]: fulfiller balance: 100000000000000000 +2024-07-15T17:32:58.155Z [INFO]: Creating listing... +2024-07-15T17:33:00.269Z [INFO]: Fulfilling listing... +2024-07-15T17:33:02.365Z [INFO]: Listing created and fulfilled. +2024-07-15T17:33:07.472Z [INFO]: Order status after fulfillment: +2024-07-15T17:33:07.472Z [INFO]: Displaying balances after sale: +2024-07-15T17:33:07.479Z [INFO]: arkReceiver balance: 1000000000000000 +2024-07-15T17:33:07.485Z [INFO]: admin balance: 989000000000000000 +2024-07-15T17:33:07.492Z [INFO]: broker balance: 10000000000000000 +2024-07-15T17:33:07.501Z [INFO]: offerer balance: 989000000000000000 +2024-07-15T17:33:07.507Z [INFO]: fulfiller balance: 0 +2024-07-15T17:36:33.846Z [INFO]: Starting the listing process... +2024-07-15T17:36:33.848Z [INFO]: Setting up accounts... +2024-07-15T17:36:33.848Z [INFO]: Accounts setup complete. +2024-07-15T17:36:33.848Z [INFO]: Setting up fees... +2024-07-15T17:37:04.168Z [INFO]: Fees setup complete. +2024-07-15T17:37:04.170Z [INFO]: Minting tokens... +2024-07-15T17:37:06.289Z [INFO]: ERC721 minting transaction hash: +2024-07-15T17:37:06.319Z [INFO]: Token minted with tokenId: +2024-07-15T17:37:06.320Z [INFO]: Minting ERC20... +2024-07-15T17:37:08.389Z [INFO]: Token minting complete. +2024-07-15T17:37:08.390Z [INFO]: Displaying balances before sale: +2024-07-15T17:37:08.405Z [INFO]: arkReceiver balance: 1000000000000000 +2024-07-15T17:37:08.414Z [INFO]: admin balance: 989000000000000000 +2024-07-15T17:37:08.421Z [INFO]: broker balance: 10000000000000000 +2024-07-15T17:37:08.428Z [INFO]: offerer balance: 989000000000000000 +2024-07-15T17:37:08.437Z [INFO]: fulfiller balance: 100000000000000000 +2024-07-15T17:37:08.437Z [INFO]: Creating listing... +2024-07-15T17:37:10.557Z [INFO]: Fulfilling listing... +2024-07-15T17:37:12.653Z [INFO]: Listing created and fulfilled. +2024-07-15T17:37:17.761Z [INFO]: Order status after fulfillment: +2024-07-15T17:37:17.761Z [INFO]: Displaying balances after sale: +2024-07-15T17:37:17.769Z [INFO]: arkReceiver balance: 2000000000000000 +2024-07-15T17:37:17.776Z [INFO]: admin balance: 1086000000000000000 +2024-07-15T17:37:17.783Z [INFO]: broker balance: 12000000000000000 +2024-07-15T17:37:17.791Z [INFO]: offerer balance: 1086000000000000000 +2024-07-15T17:37:17.798Z [INFO]: fulfiller balance: 0 +2024-07-15T17:39:41.274Z [INFO]: Starting the listing process... +2024-07-15T17:39:41.274Z [INFO]: Setting up accounts... +2024-07-15T17:39:41.275Z [INFO]: Accounts setup complete. +2024-07-15T17:39:41.275Z [INFO]: Setting up fees... +2024-07-15T17:40:11.573Z [INFO]: Fees setup complete. +2024-07-15T17:40:11.582Z [INFO]: Minting tokens... +2024-07-15T17:40:13.660Z [INFO]: ERC721 minting transaction hash: +2024-07-15T17:40:13.689Z [INFO]: Token minted with tokenId: +2024-07-15T17:40:13.689Z [INFO]: Minting ERC20... +2024-07-15T17:40:15.751Z [INFO]: Token minting complete. +2024-07-15T17:40:15.751Z [INFO]: Displaying balances before sale: +2024-07-15T17:40:15.773Z [INFO]: arkReceiver balance: 2000000000000000 +2024-07-15T17:40:15.781Z [INFO]: admin balance: 1086000000000000000 +2024-07-15T17:40:15.788Z [INFO]: broker balance: 12000000000000000 +2024-07-15T17:40:15.797Z [INFO]: offerer balance: 1086000000000000000 +2024-07-15T17:40:15.803Z [INFO]: fulfiller balance: 100000000000000000 +2024-07-15T17:40:15.804Z [INFO]: Creating listing... +2024-07-15T17:40:17.916Z [INFO]: Fulfilling listing... +2024-07-15T17:40:20.002Z [INFO]: Listing created and fulfilled. +2024-07-15T17:40:25.119Z [INFO]: Order status after fulfillment: +2024-07-15T17:40:25.120Z [INFO]: Displaying balances after sale: +2024-07-15T17:40:25.130Z [INFO]: arkReceiver balance: 3000000000000000 +2024-07-15T17:40:25.136Z [INFO]: admin balance: 1183000000000000000 +2024-07-15T17:40:25.145Z [INFO]: broker balance: 14000000000000000 +2024-07-15T17:40:25.151Z [INFO]: offerer balance: 1183000000000000000 +2024-07-15T17:40:25.158Z [INFO]: fulfiller balance: 0 +2024-07-15T17:44:45.321Z [INFO]: Starting the offer creation and fulfillment process... +2024-07-15T17:44:45.322Z [INFO]: Setting up accounts... +2024-07-15T17:44:45.322Z [INFO]: Accounts setup complete. +2024-07-15T17:44:45.322Z [INFO]: Setting up fees... +2024-07-15T17:45:15.636Z [INFO]: Fees setup complete. +2024-07-15T17:45:15.638Z [INFO]: Minting tokens... +2024-07-15T17:45:17.722Z [INFO]: ERC721 minting transaction hash: +2024-07-15T17:45:17.752Z [INFO]: Token minted with tokenId: +2024-07-15T17:45:17.752Z [INFO]: Minting ERC20... +2024-07-15T17:45:19.820Z [INFO]: Token minting complete. +2024-07-15T17:45:19.828Z [INFO]: Displaying balances before offer creation and fulfillment: +2024-07-15T17:45:19.837Z [INFO]: arkReceiver balance: 3000000000000000 +2024-07-15T17:45:19.845Z [INFO]: admin balance: 1183000000000000000 +2024-07-15T17:45:19.856Z [INFO]: broker balance: 14000000000000000 +2024-07-15T17:45:19.865Z [INFO]: offerer balance: 1183000000000000000 +2024-07-15T17:45:19.877Z [INFO]: fulfiller balance: 100000000000000000 +2024-07-15T17:45:19.877Z [INFO]: Creating offer... +2024-07-15T17:45:21.990Z [INFO]: Fulfilling offer... +2024-07-15T17:45:22.005Z [ERROR]: An error occurred: RPC: starknet_estimateFee with params { + "request": [ + { + "type": "INVOKE", + "sender_address": "0xe29882a1fcba1e7e10cad46212257fea5c752a4f9b1b1ec683c503a2cf5c8a", + "calldata": [ + "0x2", + "0x51e083b43a7c2f784ec8fb9bdfeef919c583d498f121fd8f2a78103465c066f", + "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", + "0x3", + "0x62b12cef40d34a7a2be89ee6dfd5c23b4ba2f0c69146aa33ad23dcc2b68b569", + "0xe", + "0x0", + "0x62b12cef40d34a7a2be89ee6dfd5c23b4ba2f0c69146aa33ad23dcc2b68b569", + "0x2d99282b26beeb0e75a3144ef2019a076c60e140c325804ab7f5fa28d6ec5e5", + "0x9", + "0x2f1112b92d8c48fcee45f193c95c5572136e6bbd286cc2a4d248c542b671a15", + "0x1", + "0xe29882a1fcba1e7e10cad46212257fea5c752a4f9b1b1ec683c503a2cf5c8a", + "0x4b4154414e41", + "0x51e083b43a7c2f784ec8fb9bdfeef919c583d498f121fd8f2a78103465c066f", + "0x0", + "0xe", + "0x0", + "0x56c155b624fdf6bfc94f7b37cf1dbebb5e186ef2e4ab2762367cd07c8f892a1" + ], + "version": "0x100000000000000000000000000000001", + "signature": [], + "nonce": "0x19", + "max_fee": "0x0" + } + ], + "block_id": "pending", + "simulation_flags": [ + "SKIP_VALIDATE" + ] +} + + 41: Transaction execution error: {"transaction_index":0,"execution_error":"transaction reverted: Error in the called contract (0x00e29882a1fcba1e7e10cad46212257fea5c752a4f9b1b1ec683c503a2cf5c8a):\nError at pc=0:4573:\nGot an exception while executing a hint: Hint Error: Execution failed. Failure reason: 0x4552433732313a20756e617574686f72697a65642063616c6c6572 ('ERC721: unauthorized caller').\nCairo traceback (most recent call last):\nUnknown location (pc=0:67)\nUnknown location (pc=0:1835)\nUnknown location (pc=0:2478)\nUnknown location (pc=0:3255)\nUnknown location (pc=0:3795)\n\nError in the called contract (0x051e083b43a7c2f784ec8fb9bdfeef919c583d498f121fd8f2a78103465c066f):\nExecution failed. Failure reason: 0x4552433732313a20756e617574686f72697a65642063616c6c6572 ('ERC721: unauthorized caller').\n"} +2024-07-15T17:53:17.538Z [INFO]: Starting the listing process... +2024-07-15T17:53:17.539Z [INFO]: Setting up accounts... +2024-07-15T17:53:17.539Z [INFO]: Accounts setup complete. +2024-07-15T17:53:17.539Z [INFO]: Setting up fees... +2024-07-15T17:53:47.873Z [INFO]: Fees setup complete. +2024-07-15T17:53:47.874Z [INFO]: Minting tokens... +2024-07-15T17:53:49.966Z [INFO]: ERC721 minting transaction hash: +2024-07-15T17:53:49.966Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T17:53:52.074Z [INFO]: Token minted with tokenId: +2024-07-15T17:53:52.074Z [INFO]: Token minting complete. +2024-07-15T17:53:52.075Z [INFO]: Displaying balances before sale: +2024-07-15T17:53:52.082Z [INFO]: arkReceiver balance: 3000000000000000 +2024-07-15T17:53:52.091Z [INFO]: admin balance: 1183000000000000000 +2024-07-15T17:53:52.098Z [INFO]: broker balance: 14000000000000000 +2024-07-15T17:53:52.105Z [INFO]: offerer balance: 1183000000000000000 +2024-07-15T17:53:52.117Z [INFO]: fulfiller balance: 200000000000000000 +2024-07-15T17:53:52.117Z [INFO]: Creating listing... +2024-07-15T17:53:54.239Z [INFO]: Fulfilling listing... +2024-07-15T17:53:56.359Z [INFO]: Listing created and fulfilled. +2024-07-15T17:54:01.483Z [INFO]: Order status after fulfillment: +2024-07-15T17:54:01.483Z [INFO]: Displaying balances after sale: +2024-07-15T17:54:01.499Z [INFO]: arkReceiver balance: 4000000000000000 +2024-07-15T17:54:01.506Z [INFO]: admin balance: 1280000000000000000 +2024-07-15T17:54:01.528Z [INFO]: broker balance: 16000000000000000 +2024-07-15T17:54:01.555Z [INFO]: offerer balance: 1280000000000000000 +2024-07-15T17:54:01.563Z [INFO]: fulfiller balance: 100000000000000000 +2024-07-15T17:56:11.114Z [INFO]: Starting the offer creation and fulfillment process... +2024-07-15T17:56:11.115Z [INFO]: Setting up accounts... +2024-07-15T17:56:11.115Z [INFO]: Accounts setup complete. +2024-07-15T17:56:11.115Z [INFO]: Setting up fees... +2024-07-15T17:56:41.426Z [INFO]: Fees setup complete. +2024-07-15T17:56:41.427Z [INFO]: Minting tokens... +2024-07-15T17:56:41.429Z [INFO]: Minting ERC20 for the offerer... +2024-07-15T17:56:43.518Z [INFO]: Minting ERC721 for the fulfiller... +2024-07-15T17:56:45.602Z [INFO]: ERC721 minting transaction hash: +2024-07-15T17:56:45.629Z [INFO]: Token minted with tokenId: +2024-07-15T17:56:45.629Z [INFO]: Token minting complete. +2024-07-15T17:56:45.629Z [INFO]: Displaying balances before offer creation and fulfillment: +2024-07-15T17:56:45.639Z [INFO]: arkReceiver balance: 4000000000000000 +2024-07-15T17:56:45.649Z [INFO]: admin balance: 1380000000000000000 +2024-07-15T17:56:45.656Z [INFO]: broker balance: 16000000000000000 +2024-07-15T17:56:45.665Z [INFO]: offerer balance: 1380000000000000000 +2024-07-15T17:56:45.672Z [INFO]: fulfiller balance: 100000000000000000 +2024-07-15T17:56:45.672Z [INFO]: Creating offer... +2024-07-15T17:56:47.791Z [INFO]: Fulfilling offer... +2024-07-15T17:56:49.895Z [INFO]: Offer created and fulfilled. +2024-07-15T17:56:55.006Z [INFO]: Order status after fulfillment: +2024-07-15T17:56:55.007Z [INFO]: Displaying balances after offer creation and fulfillment: +2024-07-15T17:56:55.015Z [INFO]: arkReceiver balance: 5000000000000000 +2024-07-15T17:56:55.021Z [INFO]: admin balance: 1281000000000000000 +2024-07-15T17:56:55.029Z [INFO]: broker balance: 18000000000000000 +2024-07-15T17:56:55.036Z [INFO]: offerer balance: 1281000000000000000 +2024-07-15T17:56:55.042Z [INFO]: fulfiller balance: 196000000000000000 +2024-07-15T18:03:24.634Z [INFO]: Starting the listing creation and cancellation process... +2024-07-15T18:03:24.634Z [INFO]: Setting up accounts... +2024-07-15T18:03:24.635Z [INFO]: Accounts setup complete. +2024-07-15T18:03:24.635Z [INFO]: Setting up fees... +2024-07-15T18:03:54.954Z [INFO]: Fees setup complete. +2024-07-15T18:03:54.955Z [INFO]: Minting tokens... +2024-07-15T18:03:57.042Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:03:57.042Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:03:59.149Z [INFO]: Token minted with tokenId: +2024-07-15T18:03:59.149Z [INFO]: Token minting complete. +2024-07-15T18:03:59.150Z [INFO]: Displaying balances before listing creation: +2024-07-15T18:03:59.160Z [INFO]: arkReceiver balance: 5000000000000000 +2024-07-15T18:03:59.171Z [INFO]: admin balance: 1281000000000000000 +2024-07-15T18:03:59.183Z [INFO]: broker balance: 18000000000000000 +2024-07-15T18:03:59.193Z [INFO]: offerer balance: 1281000000000000000 +2024-07-15T18:03:59.203Z [INFO]: fulfiller balance: 296000000000000000 +2024-07-15T18:03:59.203Z [INFO]: Creating listing... +2024-07-15T18:04:06.333Z [INFO]: Fetching order status after creation... +2024-07-15T18:04:06.461Z [INFO]: Order status before cancellation: +2024-07-15T18:04:06.461Z [INFO]: Cancelling listing order... +2024-07-15T18:04:10.556Z [INFO]: Fetching order status after cancellation... +2024-07-15T18:04:10.678Z [INFO]: Order status after cancellation: +2024-07-15T18:04:10.678Z [INFO]: Displaying balances after listing cancellation: +2024-07-15T18:04:10.686Z [INFO]: arkReceiver balance: 5000000000000000 +2024-07-15T18:04:10.693Z [INFO]: admin balance: 1281000000000000000 +2024-07-15T18:04:10.699Z [INFO]: broker balance: 18000000000000000 +2024-07-15T18:04:10.707Z [INFO]: offerer balance: 1281000000000000000 +2024-07-15T18:04:10.713Z [INFO]: fulfiller balance: 296000000000000000 +2024-07-15T18:04:30.027Z [INFO]: Starting the listing creation and cancellation process... +2024-07-15T18:04:30.028Z [INFO]: Setting up accounts... +2024-07-15T18:04:30.028Z [INFO]: Accounts setup complete. +2024-07-15T18:04:30.028Z [INFO]: Setting up fees... +2024-07-15T18:05:00.332Z [INFO]: Fees setup complete. +2024-07-15T18:05:00.336Z [INFO]: Minting tokens... +2024-07-15T18:05:02.415Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:05:02.415Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:05:04.495Z [INFO]: Token minted with tokenId: +2024-07-15T18:05:04.495Z [INFO]: Token minting complete. +2024-07-15T18:05:04.495Z [INFO]: Creating listing... +2024-07-15T18:05:11.619Z [INFO]: Fetching order status after creation... +2024-07-15T18:05:11.719Z [INFO]: Order status before cancellation: +2024-07-15T18:05:11.719Z [INFO]: Cancelling listing order... +2024-07-15T18:05:15.790Z [INFO]: Fetching order status after cancellation... +2024-07-15T18:05:15.884Z [INFO]: Order status after cancellation: +2024-07-15T18:08:26.088Z [INFO]: Starting the listing creation and status check process... +2024-07-15T18:08:26.089Z [INFO]: Setting up accounts... +2024-07-15T18:08:26.089Z [INFO]: Accounts setup complete. +2024-07-15T18:08:38.375Z [INFO]: Whitelisting broker 0x56c155b624fdf6bfc94f7b37cf1dbebb5e186ef2e4ab2762367cd07c8f892a1 +2024-07-15T18:08:38.496Z [ERROR]: An error occurred: RPC: starknet_estimateFee with params { + "request": [ + { + "type": "INVOKE", + "sender_address": "0x3d0ceeb06a16dc38dbde8def8bcc83dc3c014cc7a3717c42b3ab04fa691938f", + "calldata": [ + "0x1", + "0x60d908e5d7a8f450e78a621e0cc2e0e498ed5550716546a189dfd1e1db5ead1", + "0x8e4d0c9faab4180c0b7c32e7bb19d2f597721941871a63db5d21feff1e3cca", + "0x1", + "0x56c155b624fdf6bfc94f7b37cf1dbebb5e186ef2e4ab2762367cd07c8f892a1" + ], + "version": "0x100000000000000000000000000000001", + "signature": [], + "nonce": "0x1", + "max_fee": "0x0" + } + ], + "block_id": "pending", + "simulation_flags": [ + "SKIP_VALIDATE" + ] +} + + 41: Transaction execution error: {"execution_error":"transaction reverted: Error in the called contract (0x03d0ceeb06a16dc38dbde8def8bcc83dc3c014cc7a3717c42b3ab04fa691938f):\nError at pc=0:4573:\nGot an exception while executing a hint: Entry point EntryPointSelector(StarkFelt(\"0x008e4d0c9faab4180c0b7c32e7bb19d2f597721941871a63db5d21feff1e3cca\")) not found in contract.\nCairo traceback (most recent call last):\nUnknown location (pc=0:67)\nUnknown location (pc=0:1835)\nUnknown location (pc=0:2478)\nUnknown location (pc=0:3255)\nUnknown location (pc=0:3795)\n\nError in the called contract (0x060d908e5d7a8f450e78a621e0cc2e0e498ed5550716546a189dfd1e1db5ead1):\nEntry point EntryPointSelector(StarkFelt(\"0x008e4d0c9faab4180c0b7c32e7bb19d2f597721941871a63db5d21feff1e3cca\")) not found in contract.\n","transaction_index":0} +2024-07-15T18:10:04.321Z [INFO]: Starting the listing creation and status check process... +2024-07-15T18:10:04.322Z [INFO]: Setting up accounts... +2024-07-15T18:10:04.322Z [INFO]: Accounts setup complete. +2024-07-15T18:10:14.457Z [INFO]: Minting tokens... +2024-07-15T18:10:16.564Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:10:16.565Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:10:18.681Z [INFO]: Token minted with tokenId: +2024-07-15T18:10:18.681Z [INFO]: Token minting complete. +2024-07-15T18:10:18.696Z [INFO]: Owner of tokenId 19 is 0x00b3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca +2024-07-15T18:10:18.696Z [INFO]: Creating listing... +2024-07-15T18:10:20.806Z [INFO]: Order hash: +2024-07-15T18:10:20.806Z [INFO]: Fetching order status... +2024-07-15T18:10:20.893Z [INFO]: Order status: +2024-07-15T18:10:43.215Z [INFO]: Starting the listing creation and cancellation process... +2024-07-15T18:10:43.216Z [INFO]: Setting up accounts... +2024-07-15T18:10:43.216Z [INFO]: Accounts setup complete. +2024-07-15T18:10:53.330Z [INFO]: Minting tokens... +2024-07-15T18:10:55.427Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:10:55.427Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:10:57.541Z [INFO]: Token minted with tokenId: +2024-07-15T18:10:57.541Z [INFO]: Token minting complete. +2024-07-15T18:10:57.541Z [INFO]: Creating listing... +2024-07-15T18:11:04.667Z [INFO]: Fetching order status after creation... +2024-07-15T18:11:04.766Z [INFO]: Order status before cancellation: +2024-07-15T18:11:04.766Z [INFO]: Cancelling listing order... +2024-07-15T18:11:08.838Z [INFO]: Fetching order status after cancellation... +2024-07-15T18:11:08.937Z [INFO]: Order status after cancellation: +2024-07-15T18:12:36.744Z [INFO]: Starting the listing creation and status check process... +2024-07-15T18:12:36.745Z [INFO]: Setting up accounts... +2024-07-15T18:12:36.745Z [INFO]: Accounts setup complete. +2024-07-15T18:12:46.864Z [INFO]: Minting tokens... +2024-07-15T18:12:48.963Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:12:48.964Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:12:51.086Z [INFO]: Token minted with tokenId: +2024-07-15T18:12:51.087Z [INFO]: Token minting complete. +2024-07-15T18:12:51.103Z [INFO]: Owner of tokenId 21 is 0x00b3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca +2024-07-15T18:12:51.104Z [INFO]: Creating listing... +2024-07-15T18:12:53.226Z [INFO]: Order hash: +2024-07-15T18:12:53.227Z [INFO]: Fetching order status... +2024-07-15T18:12:53.345Z [INFO]: Order status: +2024-07-15T18:12:58.814Z [INFO]: Starting the listing creation and status check process... +2024-07-15T18:12:58.815Z [INFO]: Setting up accounts... +2024-07-15T18:12:58.815Z [INFO]: Accounts setup complete. +2024-07-15T18:13:08.929Z [INFO]: Minting tokens... +2024-07-15T18:13:11.022Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:13:11.022Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:13:13.112Z [INFO]: Token minted with tokenId: +2024-07-15T18:13:13.113Z [INFO]: Token minting complete. +2024-07-15T18:13:13.134Z [INFO]: Owner of tokenId 22 is 0x00b3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca +2024-07-15T18:13:13.135Z [INFO]: Creating listing... +2024-07-15T18:13:15.283Z [INFO]: Order hash: +2024-07-15T18:13:20.285Z [INFO]: Fetching order status... +2024-07-15T18:13:20.397Z [INFO]: Order status: +2024-07-15T18:14:01.436Z [INFO]: Starting the listing creation and status check process... +2024-07-15T18:14:01.437Z [INFO]: Setting up accounts... +2024-07-15T18:14:01.437Z [INFO]: Accounts setup complete. +2024-07-15T18:14:11.555Z [INFO]: Minting tokens... +2024-07-15T18:14:13.667Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:14:13.667Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:14:15.795Z [INFO]: Token minted with tokenId: +2024-07-15T18:14:15.795Z [INFO]: Token minting complete. +2024-07-15T18:14:15.815Z [INFO]: Owner of tokenId 23 is 0x00b3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca +2024-07-15T18:14:15.815Z [INFO]: Creating listing... +2024-07-15T18:14:17.946Z [INFO]: Order hash: +2024-07-15T18:14:22.947Z [INFO]: Fetching order status... +2024-07-15T18:14:23.065Z [INFO]: Order status: +2024-07-15T18:17:16.449Z [INFO]: Starting the listing process... +2024-07-15T18:17:16.449Z [INFO]: Setting up accounts... +2024-07-15T18:17:16.449Z [INFO]: Accounts setup complete. +2024-07-15T18:17:16.450Z [INFO]: Setting up fees... +2024-07-15T18:17:46.764Z [INFO]: Fees setup complete. +2024-07-15T18:17:46.768Z [INFO]: Minting tokens... +2024-07-15T18:17:48.854Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:17:48.854Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:17:50.948Z [INFO]: Token minted with tokenId: +2024-07-15T18:17:50.948Z [INFO]: Token minting complete. +2024-07-15T18:17:50.948Z [INFO]: Displaying balances before sale: +2024-07-15T18:17:50.960Z [INFO]: arkReceiver balance: 5000000000000000 +2024-07-15T18:17:50.968Z [INFO]: admin balance: 1281000000000000000 +2024-07-15T18:17:50.983Z [INFO]: broker balance: 18000000000000000 +2024-07-15T18:17:50.996Z [INFO]: offerer balance: 1281000000000000000 +2024-07-15T18:17:51.004Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:17:51.004Z [INFO]: Creating listing... +2024-07-15T18:17:53.118Z [INFO]: Fulfilling listing... +2024-07-15T18:17:55.226Z [INFO]: Listing created and fulfilled. +2024-07-15T18:18:00.339Z [INFO]: Order status after fulfillment: +2024-07-15T18:18:00.339Z [INFO]: Displaying balances after sale: +2024-07-15T18:18:00.347Z [INFO]: arkReceiver balance: 6000000000000000 +2024-07-15T18:18:00.354Z [INFO]: admin balance: 1378000000000000000 +2024-07-15T18:18:00.360Z [INFO]: broker balance: 20000000000000000 +2024-07-15T18:18:00.368Z [INFO]: offerer balance: 1378000000000000000 +2024-07-15T18:18:00.374Z [INFO]: fulfiller balance: 896000000000000000 +2024-07-15T18:21:45.067Z [INFO]: Starting the listing process... +2024-07-15T18:21:45.068Z [INFO]: Setting up accounts... +2024-07-15T18:21:45.069Z [INFO]: Accounts setup complete. +2024-07-15T18:21:45.069Z [INFO]: Setting up fees... +2024-07-15T18:22:15.370Z [INFO]: Fees setup complete. +2024-07-15T18:22:15.371Z [INFO]: Minting tokens... +2024-07-15T18:22:17.448Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:22:17.449Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:22:19.553Z [INFO]: Token minted with tokenId: +2024-07-15T18:22:19.553Z [INFO]: Token minting complete. +2024-07-15T18:22:19.553Z [INFO]: Displaying balances before sale: +2024-07-15T18:22:19.566Z [INFO]: arkReceiver balance: 6000000000000000 +2024-07-15T18:22:19.577Z [INFO]: admin balance: 1378000000000000000 +2024-07-15T18:22:19.584Z [INFO]: broker balance: 20000000000000000 +2024-07-15T18:22:19.590Z [INFO]: offerer balance: 1378000000000000000 +2024-07-15T18:22:19.598Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:22:19.598Z [INFO]: Creating listing... +2024-07-15T18:22:21.703Z [INFO]: Fulfilling listing... +2024-07-15T18:22:23.798Z [INFO]: Listing created and fulfilled. +2024-07-15T18:22:28.905Z [INFO]: Order status after fulfillment: +2024-07-15T18:22:28.905Z [INFO]: Displaying balances after sale: +2024-07-15T18:22:28.913Z [INFO]: arkReceiver balance: 7000000000000000 +2024-07-15T18:22:28.919Z [INFO]: admin balance: 1475000000000000000 +2024-07-15T18:22:28.926Z [INFO]: broker balance: 22000000000000000 +2024-07-15T18:22:28.934Z [INFO]: offerer balance: 1475000000000000000 +2024-07-15T18:22:28.940Z [INFO]: fulfiller balance: 896000000000000000 +2024-07-15T18:26:28.349Z [INFO]: Starting the listing process... +2024-07-15T18:26:28.349Z [INFO]: Setting up accounts... +2024-07-15T18:26:28.350Z [INFO]: Accounts setup complete. +2024-07-15T18:26:28.350Z [INFO]: Setting up fees... +2024-07-15T18:26:58.680Z [INFO]: Fees setup complete. +2024-07-15T18:26:58.680Z [INFO]: Minting tokens... +2024-07-15T18:27:00.758Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:27:00.758Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:27:02.859Z [INFO]: Token minted with tokenId: +2024-07-15T18:27:02.859Z [INFO]: Token minting complete. +2024-07-15T18:27:02.859Z [INFO]: Displaying balances before sale: +2024-07-15T18:27:02.873Z [INFO]: arkReceiver balance: 7000000000000000 +2024-07-15T18:27:02.881Z [INFO]: admin balance: 1475000000000000000 +2024-07-15T18:27:02.890Z [INFO]: broker balance: 22000000000000000 +2024-07-15T18:27:02.897Z [INFO]: offerer balance: 1475000000000000000 +2024-07-15T18:27:02.906Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:27:02.906Z [INFO]: Creating listing... +2024-07-15T18:27:05.053Z [INFO]: Order hash: +2024-07-15T18:27:05.053Z [INFO]: Fulfilling listing... +2024-07-15T18:27:07.160Z [INFO]: Listing created and fulfilled. +2024-07-15T18:27:12.265Z [INFO]: Order status after fulfillment: +2024-07-15T18:27:12.265Z [INFO]: Displaying balances after sale: +2024-07-15T18:27:12.272Z [INFO]: arkReceiver balance: 8000000000000000 +2024-07-15T18:27:12.278Z [INFO]: admin balance: 1572000000000000000 +2024-07-15T18:27:12.284Z [INFO]: broker balance: 24000000000000000 +2024-07-15T18:27:12.295Z [INFO]: offerer balance: 1572000000000000000 +2024-07-15T18:27:12.301Z [INFO]: fulfiller balance: 896000000000000000 +2024-07-15T18:27:40.966Z [INFO]: Starting the listing process... +2024-07-15T18:27:40.966Z [INFO]: Setting up accounts... +2024-07-15T18:27:40.966Z [INFO]: Accounts setup complete. +2024-07-15T18:27:40.967Z [INFO]: Setting up fees... +2024-07-15T18:28:11.293Z [INFO]: Fees setup complete. +2024-07-15T18:28:11.296Z [INFO]: Minting tokens... +2024-07-15T18:28:13.359Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:28:13.359Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:28:15.462Z [INFO]: Token minted with tokenId: +2024-07-15T18:28:15.462Z [INFO]: Token minting complete. +2024-07-15T18:28:15.462Z [INFO]: Displaying balances before sale: +2024-07-15T18:28:15.471Z [INFO]: arkReceiver balance: 8000000000000000 +2024-07-15T18:28:15.480Z [INFO]: admin balance: 1572000000000000000 +2024-07-15T18:28:15.488Z [INFO]: broker balance: 24000000000000000 +2024-07-15T18:28:15.496Z [INFO]: offerer balance: 1572000000000000000 +2024-07-15T18:28:15.505Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:28:15.505Z [INFO]: Creating listing... +2024-07-15T18:28:22.625Z [INFO]: Order hash: +2024-07-15T18:28:22.625Z [INFO]: Fulfilling listing... +2024-07-15T18:28:24.737Z [INFO]: Listing created and fulfilled. +2024-07-15T18:28:29.856Z [INFO]: Order status after fulfillment: +2024-07-15T18:28:29.856Z [INFO]: Displaying balances after sale: +2024-07-15T18:28:29.866Z [INFO]: arkReceiver balance: 9000000000000000 +2024-07-15T18:28:29.873Z [INFO]: admin balance: 1669000000000000000 +2024-07-15T18:28:29.881Z [INFO]: broker balance: 26000000000000000 +2024-07-15T18:28:29.887Z [INFO]: offerer balance: 1669000000000000000 +2024-07-15T18:28:29.893Z [INFO]: fulfiller balance: 896000000000000000 +2024-07-15T18:28:34.312Z [INFO]: Starting the listing process... +2024-07-15T18:28:34.312Z [INFO]: Setting up accounts... +2024-07-15T18:28:34.313Z [INFO]: Accounts setup complete. +2024-07-15T18:28:34.313Z [INFO]: Setting up fees... +2024-07-15T18:29:04.602Z [INFO]: Fees setup complete. +2024-07-15T18:29:04.604Z [INFO]: Minting tokens... +2024-07-15T18:29:06.679Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:29:06.680Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:29:08.769Z [INFO]: Token minted with tokenId: +2024-07-15T18:29:08.770Z [INFO]: Token minting complete. +2024-07-15T18:29:08.770Z [INFO]: Displaying balances before sale: +2024-07-15T18:29:08.780Z [INFO]: arkReceiver balance: 9000000000000000 +2024-07-15T18:29:08.789Z [INFO]: admin balance: 1669000000000000000 +2024-07-15T18:29:08.798Z [INFO]: broker balance: 26000000000000000 +2024-07-15T18:29:08.805Z [INFO]: offerer balance: 1669000000000000000 +2024-07-15T18:29:08.818Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:29:08.819Z [INFO]: Creating listing... +2024-07-15T18:29:15.923Z [INFO]: Order hash: +2024-07-15T18:29:15.924Z [INFO]: Fulfilling listing... +2024-07-15T18:29:18.032Z [INFO]: Listing created and fulfilled. +2024-07-15T18:29:23.137Z [INFO]: Order status after fulfillment: +2024-07-15T18:29:23.137Z [INFO]: Displaying balances after sale: +2024-07-15T18:29:23.145Z [INFO]: arkReceiver balance: 10000000000000000 +2024-07-15T18:29:23.152Z [INFO]: admin balance: 1766000000000000000 +2024-07-15T18:29:23.158Z [INFO]: broker balance: 28000000000000000 +2024-07-15T18:29:23.166Z [INFO]: offerer balance: 1766000000000000000 +2024-07-15T18:29:23.173Z [INFO]: fulfiller balance: 896000000000000000 +2024-07-15T18:31:30.674Z [INFO]: Starting the listing process... +2024-07-15T18:31:30.675Z [INFO]: Setting up accounts... +2024-07-15T18:31:30.675Z [INFO]: Accounts setup complete. +2024-07-15T18:31:30.675Z [INFO]: Setting up fees... +2024-07-15T18:32:00.980Z [INFO]: Fees setup complete. +2024-07-15T18:32:00.982Z [INFO]: Minting tokens... +2024-07-15T18:32:03.075Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:32:03.076Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:32:05.178Z [INFO]: Token minted with tokenId: +2024-07-15T18:32:05.179Z [INFO]: Token minting complete. +2024-07-15T18:32:05.179Z [INFO]: Displaying balances before sale: +2024-07-15T18:32:05.189Z [INFO]: arkReceiver balance: 10000000000000000 +2024-07-15T18:32:05.199Z [INFO]: admin balance: 1766000000000000000 +2024-07-15T18:32:05.207Z [INFO]: broker balance: 28000000000000000 +2024-07-15T18:32:05.216Z [INFO]: offerer balance: 1766000000000000000 +2024-07-15T18:32:05.224Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:32:05.224Z [INFO]: Creating listing... +2024-07-15T18:32:12.336Z [INFO]: Order hash: +2024-07-15T18:32:12.337Z [INFO]: Fulfilling listing... +2024-07-15T18:32:14.444Z [INFO]: Listing created and fulfilled. +2024-07-15T18:32:19.553Z [INFO]: Order status after fulfillment: +2024-07-15T18:32:19.553Z [INFO]: Displaying balances after sale: +2024-07-15T18:32:19.561Z [INFO]: arkReceiver balance: 11000000000000000 +2024-07-15T18:32:19.567Z [INFO]: admin balance: 1863000000000000000 +2024-07-15T18:32:19.573Z [INFO]: broker balance: 30000000000000000 +2024-07-15T18:32:19.581Z [INFO]: offerer balance: 1863000000000000000 +2024-07-15T18:32:19.588Z [INFO]: fulfiller balance: 896000000000000000 +2024-07-15T18:38:24.282Z [INFO]: Starting the listing process... +2024-07-15T18:38:24.283Z [INFO]: Setting up accounts... +2024-07-15T18:38:24.283Z [INFO]: Accounts setup complete. +2024-07-15T18:38:24.283Z [INFO]: Setting up fees... +2024-07-15T18:38:54.595Z [INFO]: Fees setup complete. +2024-07-15T18:38:54.596Z [INFO]: Minting tokens... +2024-07-15T18:38:56.669Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:38:56.669Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:38:58.762Z [INFO]: Token minted with tokenId: +2024-07-15T18:38:58.762Z [INFO]: Token minting complete. +2024-07-15T18:38:58.763Z [INFO]: Displaying balances before sale: +2024-07-15T18:38:58.775Z [INFO]: arkReceiver balance: 11000000000000000 +2024-07-15T18:38:58.783Z [INFO]: admin balance: 1863000000000000000 +2024-07-15T18:38:58.793Z [INFO]: broker balance: 30000000000000000 +2024-07-15T18:38:58.800Z [INFO]: offerer balance: 1863000000000000000 +2024-07-15T18:38:58.807Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:38:58.808Z [INFO]: Creating listing... +2024-07-15T18:39:05.922Z [INFO]: Order hash: +2024-07-15T18:39:05.923Z [INFO]: Fulfilling listing... +2024-07-15T18:39:08.033Z [INFO]: Listing created and fulfilled. +2024-07-15T18:39:13.141Z [INFO]: Order status after fulfillment: +2024-07-15T18:39:13.141Z [INFO]: Displaying balances after sale: +2024-07-15T18:39:13.149Z [INFO]: arkReceiver balance: 12000000000000000 +2024-07-15T18:39:13.155Z [INFO]: admin balance: 1960000000000000000 +2024-07-15T18:39:13.161Z [INFO]: broker balance: 32000000000000000 +2024-07-15T18:39:13.169Z [INFO]: offerer balance: 1960000000000000000 +2024-07-15T18:39:13.177Z [INFO]: fulfiller balance: 896000000000000000 +2024-07-15T18:40:03.204Z [INFO]: Starting the listing process... +2024-07-15T18:40:03.205Z [INFO]: Setting up accounts... +2024-07-15T18:40:03.205Z [INFO]: Accounts setup complete. +2024-07-15T18:40:03.205Z [INFO]: Setting up fees... +2024-07-15T18:40:33.587Z [INFO]: Fees setup complete. +2024-07-15T18:40:33.589Z [INFO]: Minting tokens... +2024-07-15T18:40:35.671Z [INFO]: ERC721 minting transaction hash: +2024-07-15T18:40:35.671Z [INFO]: Minting ERC20 for the fulfiller... +2024-07-15T18:40:37.775Z [INFO]: Token minted with tokenId: +2024-07-15T18:40:37.775Z [INFO]: Token minting complete. +2024-07-15T18:40:37.776Z [INFO]: Displaying balances before sale: +2024-07-15T18:40:37.787Z [INFO]: arkReceiver balance: 12000000000000000 +2024-07-15T18:40:37.798Z [INFO]: admin balance: 1960000000000000000 +2024-07-15T18:40:37.806Z [INFO]: broker balance: 32000000000000000 +2024-07-15T18:40:37.816Z [INFO]: offerer balance: 1960000000000000000 +2024-07-15T18:40:37.823Z [INFO]: fulfiller balance: 996000000000000000 +2024-07-15T18:40:37.823Z [INFO]: Creating listing... +2024-07-15T18:40:44.943Z [INFO]: Order hash: +2024-07-15T18:40:44.944Z [INFO]: Fulfilling listing... +2024-07-15T18:40:47.053Z [INFO]: Listing created and fulfilled. +2024-07-15T18:40:52.184Z [INFO]: Order status after fulfillment: +2024-07-15T18:40:52.184Z [INFO]: Displaying balances after sale: +2024-07-15T18:40:52.194Z [INFO]: arkReceiver balance: 13000000000000000 +2024-07-15T18:40:52.203Z [INFO]: admin balance: 2057000000000000000 +2024-07-15T18:40:52.217Z [INFO]: broker balance: 34000000000000000 +2024-07-15T18:40:52.228Z [INFO]: offerer balance: 2057000000000000000 +2024-07-15T18:40:52.235Z [INFO]: fulfiller balance: 896000000000000000 diff --git a/examples/core/package.json b/examples/core/package.json index 7b1c2bf50..c6de51792 100644 --- a/examples/core/package.json +++ b/examples/core/package.json @@ -14,7 +14,8 @@ "@ark-project/core": "workspace:*", "dotenv": "^16.4.5", "starknet": "^6.9.0", - "ts-node": "^10.9.1" + "ts-node": "^10.9.1", + "winston": "^3.13.1" }, "peerDependencies": { "typescript": "^5.0.0" diff --git a/examples/core/types/accounts.ts b/examples/core/types/accounts.ts new file mode 100644 index 000000000..985846ff6 --- /dev/null +++ b/examples/core/types/accounts.ts @@ -0,0 +1,12 @@ +import * as sn from "starknet"; + +export interface Accounts { + arkDefaultFeesReceiver: sn.Account; + admin: sn.Account; + broker_listing: sn.Account; + broker_sale: sn.Account; + offerer: sn.Account; + fulfiller: sn.Account; + arkSetbyAdminCollectionReceiver: sn.Account; + arkCollection2981Receiver: sn.Account; +} diff --git a/examples/core/utils/displayBalances.ts b/examples/core/utils/displayBalances.ts new file mode 100644 index 000000000..d7afdde1e --- /dev/null +++ b/examples/core/utils/displayBalances.ts @@ -0,0 +1,22 @@ +import { Config } from "@ark-project/core"; + +import { Accounts } from "../types/accounts.js"; +import { getBalance } from "./getBalance.js"; +import { logger } from "./logger.js"; + +export async function displayBalances( + config: Config, + accounts: Accounts, + stage: string +): Promise { + logger.info(`Displaying balances ${stage}:`); + + for (const [name, account] of Object.entries(accounts)) { + const balance = await getBalance( + config, + config.starknetCurrencyContract, + account + ); + logger.info(`${name} balance: ${balance}`); + } +} diff --git a/examples/core/utils/logger.ts b/examples/core/utils/logger.ts new file mode 100644 index 000000000..60d7b4de9 --- /dev/null +++ b/examples/core/utils/logger.ts @@ -0,0 +1,15 @@ +function getTimestamp(): string { + return new Date().toISOString(); +} + +export const logger = { + info: (...args: any[]) => { + console.log(`${getTimestamp()} [INFO]:`, ...args); + }, + error: (...args: any[]) => { + console.error(`${getTimestamp()} [ERROR]:`, ...args); + }, + warn: (...args: any[]) => { + console.warn(`${getTimestamp()} [WARN]:`, ...args); + } +}; diff --git a/examples/core/utils/mintERC721.ts b/examples/core/utils/mintERC721.ts index dad0a35dd..77c6a0f98 100644 --- a/examples/core/utils/mintERC721.ts +++ b/examples/core/utils/mintERC721.ts @@ -2,19 +2,18 @@ import { Account, Call, CallData, ProviderInterface } from "starknet"; import "dotenv/config"; -import { nftContract } from "../config/index.js"; - export async function mintERC721( provider: ProviderInterface, - starknetAccount: Account + starknetAccount: Account, + contractAddress: string ) { - const { abi: erc721abi } = await provider.getClassAt(nftContract); + const { abi: erc721abi } = await provider.getClassAt(contractAddress); if (erc721abi === undefined) { throw new Error("no abi."); } const mintCall: Call = { - contractAddress: nftContract, + contractAddress: contractAddress, entrypoint: "mint", calldata: CallData.compile({ recipient: starknetAccount.address, diff --git a/examples/core/utils/mintTokens.ts b/examples/core/utils/mintTokens.ts new file mode 100644 index 000000000..6d7e8f68d --- /dev/null +++ b/examples/core/utils/mintTokens.ts @@ -0,0 +1,58 @@ +import { Config } from "@ark-project/core"; + +import { Accounts } from "../types/accounts.js"; +import { getCurrentTokenId } from "./getCurrentTokenId.js"; +import { logger } from "./logger.js"; +import { mintERC20 } from "./mintERC20.js"; +import { mintERC721 } from "./mintERC721.js"; + +export async function mintTokens( + config: Config, + accounts: Accounts, + nftContract: string, + isOffer?: boolean +): Promise<{ tokenId: bigint; orderAmount: bigint }> { + logger.info("Minting tokens..."); + + let tokenId: bigint; + const orderAmount = BigInt(100000000000000000); + + if (isOffer) { + // For offers, mint ERC20 for offerer and ERC721 for fulfiller + logger.info("Minting ERC20 for the offerer..."); + await mintERC20(config.starknetProvider, accounts.offerer, orderAmount); + + logger.info("Minting ERC721 for the fulfiller..."); + const transaction_hash = await mintERC721( + config.starknetProvider, + accounts.fulfiller, + nftContract + ); + logger.info("ERC721 minting transaction hash:", transaction_hash); + } else { + // For listings, mint ERC721 for offerer and ERC20 for fulfiller (if in dev) + const transaction_hash = await mintERC721( + config.starknetProvider, + accounts.offerer, + nftContract + ); + logger.info("ERC721 minting transaction hash:", transaction_hash); + + if (process.env.STARKNET_NETWORK_ID === "dev") { + logger.info("Minting ERC20 for the fulfiller..."); + await mintERC20(config.starknetProvider, accounts.fulfiller, orderAmount); + } + } + + if (config.starknetNetwork !== "dev") { + logger.info("Waiting for 5 minutes for transaction to complete..."); + await new Promise((resolve) => setTimeout(resolve, 5 * 60 * 1000)); + } + + tokenId = await getCurrentTokenId(config, nftContract); + logger.info("Token minted with tokenId:", tokenId); + + logger.info("Token minting complete."); + + return { tokenId, orderAmount }; +} diff --git a/examples/core/utils/setArkFees.ts b/examples/core/utils/setArkFees.ts index 189cf3457..e7344675c 100644 --- a/examples/core/utils/setArkFees.ts +++ b/examples/core/utils/setArkFees.ts @@ -16,13 +16,14 @@ export const setArkFees = async ( const executorContract = new sn.Contract( abi, - starknetAddress, + config.starknetExecutorContract, config.starknetProvider ); + executorContract.connect(deployerAccount); const response = await executorContract.set_ark_fees({ numerator: cairo.uint256(fees), - denominator: cairo.uint256(100) + denominator: cairo.uint256(10000) }); await config.starknetProvider.waitForTransaction(response.transaction_hash); }; diff --git a/examples/core/utils/setCollectionCreatorFees.ts b/examples/core/utils/setCollectionCreatorFees.ts new file mode 100644 index 000000000..2e8502b87 --- /dev/null +++ b/examples/core/utils/setCollectionCreatorFees.ts @@ -0,0 +1,35 @@ +import { cairo } from "starknet"; +import * as sn from "starknet"; + +import { Config } from "@ark-project/core"; + +export const setCollectionCreatorFees = async ( + config: Config, + adminAccount: sn.Account, + arkCollectionReceiver: string, + fees: number, + nftAddress: string +) => { + const { abi } = await config.starknetProvider.getClassAt( + config.starknetExecutorContract + ); + if (abi === undefined) { + throw new Error("no abi."); + } + + const executorContract = new sn.Contract( + abi, + config.starknetExecutorContract, + config.starknetProvider + ); + executorContract.connect(adminAccount); + const response = await executorContract.set_collection_creator_fees( + nftAddress, + arkCollectionReceiver, + { + numerator: cairo.uint256(fees), + denominator: cairo.uint256(10000) + } + ); + await config.starknetProvider.waitForTransaction(response.transaction_hash); +}; diff --git a/examples/core/utils/setDefaultCreatorFees.ts b/examples/core/utils/setDefaultCreatorFees.ts new file mode 100644 index 000000000..e4f646df2 --- /dev/null +++ b/examples/core/utils/setDefaultCreatorFees.ts @@ -0,0 +1,33 @@ +import { cairo } from "starknet"; +import * as sn from "starknet"; + +import { Config } from "@ark-project/core"; + +export const setDefaultCreatorFees = async ( + config: Config, + deployerAccount: sn.Account, + arkReceiver: string, + fees: number +) => { + const { abi } = await config.starknetProvider.getClassAt( + config.starknetExecutorContract + ); + if (abi === undefined) { + throw new Error("no abi."); + } + + const executorContract = new sn.Contract( + abi, + config.starknetExecutorContract, + config.starknetProvider + ); + executorContract.connect(deployerAccount); + const response = await executorContract.set_default_creator_fees( + arkReceiver, + { + numerator: cairo.uint256(fees), + denominator: cairo.uint256(10000) + } + ); + await config.starknetProvider.waitForTransaction(response.transaction_hash); +}; diff --git a/examples/core/utils/setupAccounts.ts b/examples/core/utils/setupAccounts.ts new file mode 100644 index 000000000..74c1ef16b --- /dev/null +++ b/examples/core/utils/setupAccounts.ts @@ -0,0 +1,69 @@ +import { Config, fetchOrCreateAccount } from "@ark-project/core"; + +import { Accounts } from "../types/accounts.js"; +import { logger } from "./logger.js"; + +export async function setupAccounts(config: Config): Promise { + logger.info("Setting up accounts..."); + + const arkDefaultFeesReceiver = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_ARK_RECEIVER_ADDRESS!, + process.env.STARKNET_ARK_RECEIVER_PRIVATE_KEY! + ); + + const arkSetbyAdminCollectionReceiver = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_ARK_COLLECTION_RECEIVER_ADDRESS!, + process.env.STARKNET_ARK_COLLECTION_RECEIVER_PRIVATE_KEY! + ); + + const arkCollection2981Receiver = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_ARK_COLLECTION_2981_RECEIVER_ADDRESS!, + process.env.STARKNET_ARK_COLLECTION_2981_RECEIVER_PRIVATE_KEY! + ); + + const admin = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_ADMIN_ADDRESS!, + process.env.STARKNET_ADMIN_PRIVATE_KEY! + ); + + const broker_listing = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_LISTING_BROKER_ACCOUNT_ADDRESS!, + process.env.STARKNET_LISTING_BROKER_ACCOUNT_PRIVATE_KEY! + ); + + const broker_sale = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_SALE_BROKER_ACCOUNT_ADDRESS!, + process.env.STARKNET_SALE_BROKER_ACCOUNT_PRIVATE_KEY! + ); + + const offerer = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_ACCOUNT1_ADDRESS!, + process.env.STARKNET_ACCOUNT1_PRIVATE_KEY! + ); + + const fulfiller = await fetchOrCreateAccount( + config.starknetProvider, + process.env.STARKNET_ACCOUNT2_ADDRESS!, + process.env.STARKNET_ACCOUNT2_PRIVATE_KEY! + ); + + logger.info("Accounts setup complete."); + + return { + arkDefaultFeesReceiver, + admin, + broker_listing, + broker_sale, + offerer, + fulfiller, + arkSetbyAdminCollectionReceiver, + arkCollection2981Receiver + }; +} diff --git a/examples/core/utils/setupFees.ts b/examples/core/utils/setupFees.ts new file mode 100644 index 000000000..a309da6a5 --- /dev/null +++ b/examples/core/utils/setupFees.ts @@ -0,0 +1,50 @@ +import { Config, createBroker } from "@ark-project/core"; + +import { contracts, isDev } from "../config/index.js"; +import { Accounts } from "../types/accounts.js"; +import { logger } from "./logger.js"; +import { setArkFees } from "./setArkFees.js"; +import { setCollectionCreatorFees } from "./setCollectionCreatorFees.js"; +import { setDefaultCreatorFees } from "./setDefaultCreatorFees.js"; + +export async function setupFees( + config: Config, + accounts: Accounts +): Promise { + logger.info("Setting up fees..."); + + if (!isDev || !("nftContract" in contracts)) { + throw new Error("NFT contract is not available in this environment"); + } + + await setArkFees(config, accounts.admin, config.starknetExecutorContract, 25); + + await createBroker(config, { + brokenAccount: accounts.broker_listing, + numerator: 50, + denominator: 10000 + }); + + await createBroker(config, { + brokenAccount: accounts.broker_sale, + numerator: 50, + denominator: 10000 + }); + + await setCollectionCreatorFees( + config, + accounts.admin, + accounts.arkSetbyAdminCollectionReceiver.address, + 50, + contracts.nftContractFixedFees + ); + + await setDefaultCreatorFees( + config, + accounts.admin, + accounts.arkDefaultFeesReceiver.address, + 50 + ); + + logger.info("Fees setup complete."); +} diff --git a/packages/core/src/actions/broker/createBroker.ts b/packages/core/src/actions/broker/createBroker.ts index e505c02d7..633df3d62 100644 --- a/packages/core/src/actions/broker/createBroker.ts +++ b/packages/core/src/actions/broker/createBroker.ts @@ -1,30 +1,30 @@ -import { Account, CallData } from "starknet"; +import { Account, cairo, CallData } from "starknet"; import { Config } from "../../createConfig.js"; interface Params { - brokerID: string; + brokenAccount: Account; + numerator: number; + denominator: number; } export const createBroker = async (config: Config, params: Params) => { - const address = process.env.SOLIS_ADMIN_ADDRESS as string; - const privateKey = process.env.SOLIS_ADMIN_PRIVATE_KEY as string; - const account = new Account(config.arkProvider, address, privateKey, "1"); - const whitelist_broker_calldata = CallData.compile({ - broker_id: params.brokerID + fees_ratio: { + numerator: cairo.uint256(params.numerator), + denominator: cairo.uint256(params.denominator) + } }); - const result = await account.execute({ - contractAddress: config.arkchainOrderbookContract, - entrypoint: "whitelist_broker", + const result = await params.brokenAccount.execute({ + contractAddress: config.starknetExecutorContract, + entrypoint: "set_broker_fees", calldata: whitelist_broker_calldata }); - await config.arkProvider.waitForTransaction(result.transaction_hash); + await config.starknetProvider.waitForTransaction(result.transaction_hash); return { - brokerID: params.brokerID, transactionHash: result.transaction_hash }; }; diff --git a/packages/core/src/actions/order/createListing.ts b/packages/core/src/actions/order/createListing.ts index 6da019da8..993f51256 100644 --- a/packages/core/src/actions/order/createListing.ts +++ b/packages/core/src/actions/order/createListing.ts @@ -67,12 +67,7 @@ const createListing = async ( brokerId: baseOrder.brokerId, additionalData: [] }; - console.log(order); - console.log( - CallData.compile({ - order: order - }) - ); + const result = await starknetAccount.execute([ { contractAddress: approveInfo.tokenAddress as string, diff --git a/packages/core/src/actions/order/fulfillListing.ts b/packages/core/src/actions/order/fulfillListing.ts index 600336c9f..5bae3dd38 100644 --- a/packages/core/src/actions/order/fulfillListing.ts +++ b/packages/core/src/actions/order/fulfillListing.ts @@ -47,7 +47,6 @@ const fulfillListing = async ( fulfillBrokerAddress: fulfillListingInfo.brokerId }; - console.log("Fulfilling order with the following info:", fulfillInfo); const result = await starknetAccount.execute([ { contractAddress: approveInfo.currencyAddress as string, diff --git a/packages/core/src/contracts.ts b/packages/core/src/contracts.ts index 95719b7f2..e71f820e1 100644 --- a/packages/core/src/contracts.ts +++ b/packages/core/src/contracts.ts @@ -1,14 +1,12 @@ // This file is auto-generated. Do not edit directly. export const SEPOLIA_CONTRACTS = { - messaging: - "0x74f13f1dffb5ad3c051d535ba03514e653b6dcac68e30b2db66a0aa0217c815", - executor: "0xb86ab357c15c12fb78f9b0a19fa974c730fcbab96f17881827dde871665f0b", - orderbook: "0x795b605fa3144afd6f11a4499f71b9cf373bcba3f1b2835d51f65ab59392261" + "messaging": "0x74f13f1dffb5ad3c051d535ba03514e653b6dcac68e30b2db66a0aa0217c815", + "executor": "0xb86ab357c15c12fb78f9b0a19fa974c730fcbab96f17881827dde871665f0b", + "orderbook": "0x795b605fa3144afd6f11a4499f71b9cf373bcba3f1b2835d51f65ab59392261" }; export const MAINNET_CONTRACTS = { - messaging: - "0x57d45cc46de463f7ae63b74ce9b6b6b496a1178b02e7ad04d7c307caa698b7b", - executor: "0x7b42945bc47001db92fe1b9739d753925263f2f1036c2ae1f87536c916ee6a", - orderbook: "0x51d61ee6b0814a990a82fa7c8d9515c19f82d4bdb34e35e3d00762caa752bdb" + "messaging": "0x57d45cc46de463f7ae63b74ce9b6b6b496a1178b02e7ad04d7c307caa698b7b", + "executor": "0x7b42945bc47001db92fe1b9739d753925263f2f1036c2ae1f87536c916ee6a", + "orderbook": "0x51d61ee6b0814a990a82fa7c8d9515c19f82d4bdb34e35e3d00762caa752bdb" }; diff --git a/packages/deployer/scripts/deploy-starknet-local.ts b/packages/deployer/scripts/deploy-starknet-local.ts index 4b64bd322..3da57f62d 100644 --- a/packages/deployer/scripts/deploy-starknet-local.ts +++ b/packages/deployer/scripts/deploy-starknet-local.ts @@ -6,6 +6,7 @@ import { Account, RpcProvider } from "starknet"; import { ARTIFACTS_PATH } from "../src/constants"; import { deployERC20 } from "../src/contracts/erc20"; import { deployERC721 } from "../src/contracts/erc721"; +import { deployERC721Royalties } from "../src/contracts/erc721royalties"; import { deployExecutor } from "../src/contracts/executor"; import { deployMessaging } from "../src/contracts/messaging"; import { getFeeAddress } from "../src/providers"; @@ -63,7 +64,24 @@ async function run() { const nftContract = await deployERC721( ARTIFACTS_PATH, starknetAdminAccount, - provider + provider, + "ARKTEST", + "ARKTEST" + ); + + const nftContractFixedFees = await deployERC721( + ARTIFACTS_PATH, + starknetAdminAccount, + provider, + "ARKTESTFIXEDFEES", + "ARKTESTFIXEDFEES" + ); + + const nftContractRoyalties = await deployERC721Royalties( + ARTIFACTS_PATH, + starknetAdminAccount, + provider, + "0x29873c310fbefde666dc32a1554fea6bb45eecc84f680f8a2b0a8fbb8cb89af" ); const messagingConfigFilePath = resolve( @@ -86,6 +104,8 @@ async function run() { messaging: messagingContract.address, executor: executorContract.address, nftContract: nftContract.address, + nftContractFixedFees: nftContractFixedFees.address, + nftContractRoyalties: nftContractRoyalties.address, eth: ethContract.address }); await fs.writeFile(contractsFilePath, contractsContent); diff --git a/packages/deployer/src/contracts/erc721.ts b/packages/deployer/src/contracts/erc721.ts index bb169330a..b4aa7f9d6 100644 --- a/packages/deployer/src/contracts/erc721.ts +++ b/packages/deployer/src/contracts/erc721.ts @@ -5,14 +5,16 @@ import { loadArtifacts } from "../contracts/common"; export async function deployERC721( artifactsPath: string, deployerAccount: Account, - provider: RpcProvider + provider: RpcProvider, + name: string, + symbol: string ) { const artifacts = loadArtifacts(artifactsPath, "ark_tokens_FreeMintNFT"); const contractCallData = new CallData(artifacts.sierra.abi); const contractConstructor = contractCallData.compile("constructor", { - name: "ARKTEST", - symbol: "ARKTEST", + name: name, + symbol: symbol, base_uri: "https://ipfs.io/ipfs/QmVXJ2eEx3xrD2mSdPqLBEEYM5obj6DRYkn5yant6rXPmw/" }); diff --git a/packages/deployer/src/contracts/erc721royalties.ts b/packages/deployer/src/contracts/erc721royalties.ts new file mode 100644 index 000000000..00a48c5ab --- /dev/null +++ b/packages/deployer/src/contracts/erc721royalties.ts @@ -0,0 +1,63 @@ +import { Account, CallData, Contract, RpcProvider } from "starknet"; + +import { loadArtifacts } from "../contracts/common"; + +export async function setDefaultFees( + provider: RpcProvider, + deployerAccount: Account, + contractAddress: string, + receiver: string +) { + const { abi } = await provider.getClassAt(contractAddress); + if (abi === undefined) { + throw new Error("no abi."); + } + const tokenContract = new Contract(abi, contractAddress, provider); + tokenContract.connect(deployerAccount); + + const response = await tokenContract.set_default_royalty(receiver, { + numerator: 75, + denominator: 10000 + }); + await provider.waitForTransaction(response.transaction_hash); +} + +export async function deployERC721Royalties( + artifactsPath: string, + deployerAccount: Account, + provider: RpcProvider, + feeReceiver: string +) { + const artifacts = loadArtifacts( + artifactsPath, + "ark_tokens_FreeMintNFTRoyalty" + ); + + const contractCallData = new CallData(artifacts.sierra.abi); + const contractConstructor = contractCallData.compile("constructor", { + name: "ARKTESTROYALTY", + symbol: "ATR", + base_uri: + "https://ipfs.io/ipfs/QmVXJ2eEx3xrD2mSdPqLBEEYM5obj6DRYkn5yant6rXPmw/", + owner: deployerAccount.address // deployer is the owner in our case + }); + + const deployR = await deployerAccount.declareAndDeploy({ + contract: artifacts.sierra, + casm: artifacts.casm, + constructorCalldata: contractConstructor + }); + + setDefaultFees( + provider, + deployerAccount, + deployR.deploy.contract_address, + feeReceiver + ); + + return new Contract( + artifacts.sierra.abi, + deployR.deploy.contract_address, + provider + ); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0b3f7c9a1..d15545df0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -219,10 +219,13 @@ importers: typescript: specifier: ^5.0.0 version: 5.4.5 + winston: + specifier: ^3.13.1 + version: 3.13.1 devDependencies: '@types/bun': specifier: latest - version: 1.1.3 + version: 1.1.6 packages/core: dependencies: @@ -641,10 +644,17 @@ packages: '@changesets/write@0.3.1': resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@esbuild/aix-ppc64@0.19.12': resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} engines: {node: '>=12'} @@ -962,6 +972,7 @@ packages: '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -969,6 +980,7 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead '@ianvs/prettier-plugin-sort-imports@4.2.1': resolution: {integrity: sha512-NKN1LVFWUDGDGr3vt+6Ey3qPeN/163uR1pOPAlkWpgvAqgxQ6kSdUf1F0it8aHUtKRUzEGcK38Wxd07O61d7+Q==} @@ -1948,8 +1960,8 @@ packages: '@types/babel__traverse@7.20.6': resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - '@types/bun@1.1.3': - resolution: {integrity: sha512-i+mVz8C/lx+RprDR6Mr402iE1kmajgJPnmSfJ/NvU85sGGXSylYZ/6yc+XhVLr2E/t8o6HmjwV0evtnUOR0CFA==} + '@types/bun@1.1.6': + resolution: {integrity: sha512-uJgKjTdX0GkWEHZzQzFsJkWp5+43ZS7HC8sZPFnOwnSo1AsNl2q9o2bFeS23disNDqbggEgyFkKCHl/w8iZsMA==} '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -2005,6 +2017,9 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/ws@8.5.10': resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} @@ -2262,6 +2277,9 @@ packages: ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + autoprefixer@10.4.19: resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} engines: {node: ^10 || ^12 || >=14} @@ -2361,11 +2379,12 @@ packages: bun-types@1.1.10: resolution: {integrity: sha512-oBsZ0Bf9HEKr1Ta5bUYgVO6sHkZtTlfHlEj9DGpghZphNdhKI/38eZ5dk+/et/HrStT1sfykHBUW4ughmoNKog==} - bun-types@1.1.9: - resolution: {integrity: sha512-3YuLiH4Ne/ghk7K6mHiaqCqKOMrtB0Z5p1WAskHSVgi0iMZgsARV4yGkbfi565YsStvUq6GXTWB3ga7M8cznkA==} + bun-types@1.1.17: + resolution: {integrity: sha512-Z4+OplcSd/YZq7ZsrfD00DKJeCwuNY96a1IDJyR73+cTBaFIS7SC6LhpY/W3AMEXO9iYq5NJ58WAwnwL1p5vKg==} bun@1.1.10: resolution: {integrity: sha512-qOJXrQZSzJ5DbJMt47GZGWtUSmIkbwD7fPSN/XS/T46D4cTTnPK46QDHlyC8VD+Anvs6uKNwuwKIyB31kUdHmQ==} + cpu: [arm64, x64] os: [darwin, linux, win32] hasBin: true @@ -2502,10 +2521,19 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + colors-cli@1.0.33: resolution: {integrity: sha512-PWGsmoJFdOB0t+BeHgmtuoRZUQucOLl5ii81NBzOOGVxlgE04muFNHlR5j8i8MKbOPELBl3243AI6lGBTj5ICQ==} hasBin: true + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + commander@11.1.0: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} @@ -2721,6 +2749,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + enhanced-resolve@5.16.1: resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} engines: {node: '>=10.13.0'} @@ -3043,6 +3074,9 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -3080,6 +3114,9 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -3334,6 +3371,9 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -3733,6 +3773,9 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -3797,6 +3840,10 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + logform@2.6.1: + resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==} + engines: {node: '>= 12.0.0'} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -4029,6 +4076,9 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -4360,6 +4410,10 @@ packages: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -4461,6 +4515,10 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + safe-stable-stringify@2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -4524,6 +4582,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -4584,6 +4645,9 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -4629,6 +4693,9 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4720,6 +4787,9 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -4767,6 +4837,10 @@ packages: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -5084,6 +5158,14 @@ packages: engines: {node: '>= 8'} hasBin: true + winston-transport@4.7.1: + resolution: {integrity: sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==} + engines: {node: '>= 12.0.0'} + + winston@3.13.1: + resolution: {integrity: sha512-SvZit7VFNvXRzbqGHsv5KSmgbEYR5EiQfDAL9gxYkRqa934Hnk++zze0wANKtMHcy/gI4W/3xmSDwlhf865WGw==} + engines: {node: '>= 12.0.0'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -5556,10 +5638,18 @@ snapshots: human-id: 1.0.2 prettier: 2.8.8 + '@colors/colors@1.6.0': {} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + '@esbuild/aix-ppc64@0.19.12': optional: true @@ -5788,7 +5878,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -5833,7 +5923,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -5851,7 +5941,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.12.12 + '@types/node': 20.13.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -5873,7 +5963,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.12.12 + '@types/node': 20.13.0 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -6876,15 +6966,15 @@ snapshots: dependencies: '@babel/types': 7.24.6 - '@types/bun@1.1.3': + '@types/bun@1.1.6': dependencies: - bun-types: 1.1.9 + bun-types: 1.1.17 '@types/estree@1.0.5': {} '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.13.0 '@types/istanbul-lib-coverage@2.0.6': {} @@ -6934,6 +7024,8 @@ snapshots: '@types/stack-utils@2.0.3': {} + '@types/triple-beam@1.3.5': {} + '@types/ws@8.5.10': dependencies: '@types/node': 20.12.12 @@ -7261,6 +7353,8 @@ snapshots: ast-types-flow@0.0.8: {} + async@3.2.5: {} + autoprefixer@10.4.19(postcss@8.4.38): dependencies: browserslist: 4.23.0 @@ -7397,7 +7491,7 @@ snapshots: '@types/node': 20.12.12 '@types/ws': 8.5.10 - bun-types@1.1.9: + bun-types@1.1.17: dependencies: '@types/node': 20.12.12 '@types/ws': 8.5.10 @@ -7554,8 +7648,23 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + colors-cli@1.0.33: {} + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + commander@11.1.0: {} commander@4.1.1: {} @@ -7740,6 +7849,8 @@ snapshots: emoji-regex@9.2.2: {} + enabled@2.0.0: {} + enhanced-resolve@5.16.1: dependencies: graceful-fs: 4.2.11 @@ -7914,7 +8025,7 @@ snapshots: eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.34.2(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -7951,7 +8062,7 @@ snapshots: enhanced-resolve: 5.16.1 eslint: 8.57.0 eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.13.1 @@ -8007,33 +8118,6 @@ snapshots: eslint: 8.57.0 ignore: 5.3.1 - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): - dependencies: - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 @@ -8317,6 +8401,8 @@ snapshots: dependencies: bser: 2.1.1 + fecha@4.2.3: {} + fetch-blob@3.2.0: dependencies: node-domexception: 1.0.0 @@ -8360,6 +8446,8 @@ snapshots: flatted@3.3.1: {} + fn.name@1.1.0: {} + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -8614,6 +8702,8 @@ snapshots: is-arrayish@0.2.1: {} + is-arrayish@0.3.2: {} + is-async-function@2.0.0: dependencies: has-tostringtag: 1.0.2 @@ -8811,7 +8901,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -8905,7 +8995,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -8915,7 +9005,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.12.12 + '@types/node': 20.13.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -8954,7 +9044,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -8989,7 +9079,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -9017,7 +9107,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -9082,7 +9172,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.12 + '@types/node': 20.13.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -9091,7 +9181,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.12.12 + '@types/node': 20.13.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -9174,6 +9264,8 @@ snapshots: kleur@4.1.5: {} + kuler@2.0.0: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -9229,6 +9321,15 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + logform@2.6.1: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.4.3 + triple-beam: 1.4.1 + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -9492,6 +9593,10 @@ snapshots: dependencies: wrappy: 1.0.2 + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -9790,6 +9895,12 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -9912,6 +10023,8 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 + safe-stable-stringify@2.4.3: {} + safer-buffer@2.1.2: {} scheduler@0.23.2: @@ -9971,6 +10084,10 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + simple-update-notifier@2.0.0: dependencies: semver: 7.6.2 @@ -10037,6 +10154,8 @@ snapshots: sprintf-js@1.0.3: {} + stack-trace@0.0.10: {} + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 @@ -10118,6 +10237,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -10219,6 +10342,8 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 + text-hex@1.0.0: {} + text-table@0.2.0: {} thenify-all@1.6.0: @@ -10260,6 +10385,8 @@ snapshots: trim-newlines@3.0.1: {} + triple-beam@1.4.1: {} + ts-api-utils@1.3.0(typescript@5.4.5): dependencies: typescript: 5.4.5 @@ -10627,6 +10754,26 @@ snapshots: dependencies: isexe: 2.0.0 + winston-transport@4.7.1: + dependencies: + logform: 2.6.1 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.13.1: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.5 + is-stream: 2.0.1 + logform: 2.6.1 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.4.3 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.7.1 + word-wrap@1.2.5: {} workerpool@6.2.1: {} diff --git a/turbo.json b/turbo.json index b73551225..f03f88b17 100644 --- a/turbo.json +++ b/turbo.json @@ -128,6 +128,8 @@ "STARKNET_NETWORK_ID", "STARKNET_NFT_ADDRESS_DEV", "STARKNET_RPC_URL", + "STARKNET_ADMIN_PRIVATE_KEY", + "STARKNET_ADMIN_ADDRESS", "SOLIS_ADMIN_PUBLIC_KEY_DEV", "SOLIS_ADMIN_ADDRESS_SEPOLIA", "SOLIS_ADMIN_PRIVATE_KEY_SEPOLIA", From e33d9d07f0480334ace0aa42da05552c6f1c706a Mon Sep 17 00:00:00 2001 From: kwiss Date: Wed, 17 Jul 2024 18:13:18 +0200 Subject: [PATCH 9/9] feat(deploy): update deployer --- packages/deployer/src/contracts/setFees.ts | 77 +++++++++++++++++++ .../deployer/src/deployStarknetContracts.ts | 18 +++++ .../deployer/src/deployStarknetFreemintNft.ts | 30 -------- 3 files changed, 95 insertions(+), 30 deletions(-) create mode 100644 packages/deployer/src/contracts/setFees.ts diff --git a/packages/deployer/src/contracts/setFees.ts b/packages/deployer/src/contracts/setFees.ts new file mode 100644 index 000000000..b185dd033 --- /dev/null +++ b/packages/deployer/src/contracts/setFees.ts @@ -0,0 +1,77 @@ +import { cairo } from "starknet"; +import * as sn from "starknet"; + +export const setArkFees = async ( + starknetExecutorContract: string, + provider: sn.Provider, + deployerAccount: sn.Account, + fees: number +) => { + const { abi } = await provider.getClassAt(starknetExecutorContract); + if (abi === undefined) { + throw new Error("no abi."); + } + + const executorContract = new sn.Contract( + abi, + starknetExecutorContract, + provider + ); + + executorContract.connect(deployerAccount); + const response = await executorContract.set_ark_fees({ + numerator: cairo.uint256(fees), + denominator: cairo.uint256(10000) + }); + await provider.waitForTransaction(response.transaction_hash); +}; + +export const setDefaultCreatorFees = async ( + starknetExecutorContract: string, + provider: sn.Provider, + deployerAccount: sn.Account, + arkReceiver: string, + fees: number +) => { + const { abi } = await provider.getClassAt(starknetExecutorContract); + if (abi === undefined) { + throw new Error("no abi."); + } + + const executorContract = new sn.Contract( + abi, + starknetExecutorContract, + provider + ); + executorContract.connect(deployerAccount); + const response = await executorContract.set_default_creator_fees( + arkReceiver, + { + numerator: cairo.uint256(fees), + denominator: cairo.uint256(10000) + } + ); + await provider.waitForTransaction(response.transaction_hash); +}; + +export const setBrokerFees = async ( + provider: sn.Provider, + deployerAccount: sn.Account, + executorAddress: string +) => { + const { abi } = await provider.getClassAt(executorAddress); + if (abi === undefined) { + throw new Error("no abi."); + } + + const executorContract = new sn.Contract(abi, executorAddress, provider); + executorContract.connect(deployerAccount); + const response = await executorContract.set_broker_fees( + "0x00cb88c43637d96793e1925d357f543eb2be1b7bfb149bb666e4efa6c645ad35", + { + numerator: cairo.uint256(75), + denominator: cairo.uint256(10000) + } + ); + await provider.waitForTransaction(response.transaction_hash); +}; diff --git a/packages/deployer/src/deployStarknetContracts.ts b/packages/deployer/src/deployStarknetContracts.ts index acd50366c..deeacbfb1 100644 --- a/packages/deployer/src/deployStarknetContracts.ts +++ b/packages/deployer/src/deployStarknetContracts.ts @@ -12,6 +12,7 @@ import loading from "loading-cli"; import { ARTIFACTS_PATH } from "./constants"; import { deployExecutor, upgradeExecutor } from "./contracts/executor"; import { deployMessaging, upgradeMessaging } from "./contracts/messaging"; +import { setArkFees, setDefaultCreatorFees } from "./contracts/setFees"; import { getFeeAddress, getStarknetProvider } from "./providers"; import { getContractsFilePath, @@ -130,6 +131,23 @@ async function deployStarknetContracts(starknetNetwork: ProviderNetwork) { JSON.stringify(contractsContent, null, 2) ); + // Set Ark Fees + await await setArkFees( + executorContract.address, + starknetProvider, + starknetAdminAccount, + 25 + ); + + // Set default creator Fees + await setDefaultCreatorFees( + executorContract.address, + starknetProvider, + starknetAdminAccount, + "0x06bC109475810df11c7f046Ad72A5a52aAd8658123CC529309910d00bD4904C8", + 50 + ); + starknetSpinner.stop(); console.log("STARKNET CONTRACTS"); console.log("==================\n"); diff --git a/packages/deployer/src/deployStarknetFreemintNft.ts b/packages/deployer/src/deployStarknetFreemintNft.ts index ee6a7e255..5196063c7 100644 --- a/packages/deployer/src/deployStarknetFreemintNft.ts +++ b/packages/deployer/src/deployStarknetFreemintNft.ts @@ -5,7 +5,6 @@ import { CallData, Contract } from "starknet"; import { ARTIFACTS_PATH } from "./constants"; import { loadArtifacts } from "./contracts/common"; -import { deployERC20 } from "./contracts/erc20"; import { getStarknetProvider } from "./providers"; import { ProviderNetwork } from "./types"; import { @@ -53,36 +52,7 @@ export async function deployStarknetContracts( await fs.writeFile(getContractsFilePath(), JSON.stringify(existingContracts)); - let ethContract: Contract | undefined; - - if (starknetNetwork === "dev") { - ethContract = await deployERC20( - ARTIFACTS_PATH, - starknetAdminAccount, - starknetProvider, - "ETH", - "ETH" - ); - - existingContracts = { - ...existingContracts, - [starknetNetwork]: { - ...existingContracts[starknetNetwork], - eth: ethContract.address - } - }; - - await fs.writeFile( - getContractsFilePath(), - JSON.stringify(existingContracts) - ); - } - console.log("- Nft contract: ", nftContract.address); - - if (ethContract) { - console.log("- Eth contract: ", ethContract.address); - } } program.option("-sn, --starknet ", "Starknet Network", "dev");