Copy use std::str::FromStr;
use fuels::{
accounts::wallet::Wallet, prelude::*, types::{
Bits256, ContractId, Identity
}
};
/////////////////////////////////////Setup/////////////////////////////////////
abigen!(
Contract(
name = "AssetManager",
abi = "/home/schnilch/Fuel/thunder-nft/contracts-v1/asset_manager/out/debug/asset_manager-abi.json"
),
Contract(
name = "ExecutionManager",
abi = "/home/schnilch/Fuel/thunder-nft/contracts-v1/execution_manager/out/debug/execution_manager-abi.json"
),
Contract(
name = "ThunderExchange",
abi = "/home/schnilch/Fuel/thunder-nft/contracts-v1/thunder_exchange/out/debug/thunder_exchange-abi.json"
),
Contract(
name = "Pool",
abi = "/home/schnilch/Fuel/thunder-nft/contracts-v1/pool/out/debug/pool-abi.json"
),
Contract(
name = "RoyaltyManager",
abi = "/home/schnilch/Fuel/thunder-nft/contracts-v1/royalty_manager/out/debug/royalty_manager-abi.json"
),
Contract(
name = "Strategy",
abi = "/home/schnilch/Fuel/thunder-nft/contracts-v1/execution_strategies/strategy_fixed_price_sale/out/debug/strategy_fixed_price_sale-abi.json"
),
Contract(
name = "ERC1155",
abi = "/home/schnilch/Fuel/thunder-nft/contracts-v1/erc1155/out/debug/erc1155-abi.json"
)
);
pub type Accounts = [WalletUnlocked; 5];
const STRATEGY_FEE: u64 = 50;
const ROYALTY_MANAGER_FEE_LIMIT: u64 = 500;
pub const BASE_ASSET: AssetId = AssetId::new([0u8; 32]);
pub const ERC1155_NFT_STR: &str = "53a2ce8ca7a1cecfd3c9256797d8edce464f4d6deef427cad7b68a32f4340b0c";
pub async fn get_wallets() -> Accounts {
let mut wallets = launch_custom_provider_and_get_wallets(
WalletsConfig::new(
Some(5), /* Single wallet */
Some(1), /* Single coin (UTXO) */
Some(1_000_000_000), /* Amount per coin */
),
None,
None,
)
.await
.unwrap();
let owner = wallets.pop().unwrap();
let alice = wallets.pop().unwrap();
let bob = wallets.pop().unwrap();
let user1 = wallets.pop().unwrap();
let user2 = wallets.pop().unwrap();
[owner, alice, bob, user1, user2]
}
//The following functions set up all required contracts and initialize them
pub async fn setup_asset_manager(owner: WalletUnlocked) -> (AssetManager<WalletUnlocked>, ContractId){
let asset_manager_id = Contract::load_from(
"/home/schnilch/Fuel/thunder-nft/contracts-v1/asset_manager/out/debug/asset_manager.bin",
LoadConfiguration::default(),
)
.unwrap()
.deploy(&owner, TxPolicies::default())
.await
.unwrap();
let asset_manager = AssetManager::new(asset_manager_id.clone(), owner.clone());
asset_manager.methods().initialize().call().await.unwrap();
(asset_manager, asset_manager_id.into())
}
pub async fn setup_execution_manager(owner: WalletUnlocked) -> (ExecutionManager<WalletUnlocked>, ContractId) {
let execution_manager_id = Contract::load_from(
"/home/schnilch/Fuel/thunder-nft/contracts-v1/execution_manager/out/debug/execution_manager.bin",
LoadConfiguration::default(),
)
.unwrap()
.deploy(&owner, TxPolicies::default())
.await
.unwrap();
let execution_manager = ExecutionManager::new(execution_manager_id.clone(), owner.clone());
execution_manager.methods().initialize().call().await.unwrap();
(execution_manager, execution_manager_id.into())
}
pub async fn setup_thunder_exchange(owner: WalletUnlocked) -> (ThunderExchange<WalletUnlocked>, ContractId){
let thunder_exchange_id = Contract::load_from(
"/home/schnilch/Fuel/thunder-nft/contracts-v1/thunder_exchange/out/debug/thunder_exchange.bin",
LoadConfiguration::default(),
)
.unwrap()
.deploy(&owner, TxPolicies::default())
.await
.unwrap();
let thunder_exchange = ThunderExchange::new(thunder_exchange_id.clone(), owner.clone());
thunder_exchange.methods().initialize().call().await.unwrap();
(thunder_exchange, thunder_exchange_id.into())
}
pub async fn setup_pool(owner: WalletUnlocked, thunder_exchange: ContractId, asset_manager: ContractId) -> (Pool<WalletUnlocked>, ContractId){
let pool_id = Contract::load_from(
"/home/schnilch/Fuel/thunder-nft/contracts-v1/pool/out/debug/pool.bin",
LoadConfiguration::default(),
)
.unwrap()
.deploy(&owner, TxPolicies::default())
.await
.unwrap();
let pool = Pool::new(pool_id.clone(), owner.clone());
pool.methods().initialize(thunder_exchange, asset_manager).call().await.unwrap();
(pool, pool_id.into())
}
pub async fn setup_royalty_manager(owner: WalletUnlocked) -> (RoyaltyManager<WalletUnlocked>, ContractId){
let royalty_manager_id = Contract::load_from(
"/home/schnilch/Fuel/thunder-nft/contracts-v1/royalty_manager/out/debug/royalty_manager.bin",
LoadConfiguration::default(),
)
.unwrap()
.deploy(&owner, TxPolicies::default())
.await
.unwrap();
let royalty_manager = RoyaltyManager::new(royalty_manager_id.clone(), owner.clone());
royalty_manager.methods().initialize().call().await.unwrap();
(royalty_manager, royalty_manager_id.into())
}
pub async fn setup_strategy(owner: WalletUnlocked, thunder_exchange: ContractId) -> (Strategy<WalletUnlocked>, ContractId){
let strategy_id = Contract::load_from(
"/home/schnilch/Fuel/thunder-nft/contracts-v1/execution_strategies/strategy_fixed_price_sale/out/debug/strategy_fixed_price_sale.bin",
LoadConfiguration::default(),
)
.unwrap()
.deploy(&owner, TxPolicies::default())
.await
.unwrap();
let strategy = Strategy::new(strategy_id.clone(), owner.clone());
strategy.methods().initialize(thunder_exchange).call().await.unwrap();
(strategy, strategy_id.into())
}
pub async fn setup_erc1155(owner: WalletUnlocked, nft_holder: Address) -> (ERC1155<WalletUnlocked>, ContractId) {
let erc1155_id = Contract::load_from(
"/home/schnilch/Fuel/thunder-nft/contracts-v1/erc1155/out/debug/erc1155.bin",
LoadConfiguration::default(),
)
.unwrap()
.deploy(&owner, TxPolicies::default())
.await
.unwrap();
let erc1155 = ERC1155::new(erc1155_id.clone(), owner.clone());
erc1155.methods().constructor(Identity::Address(owner.address().into())).call().await.unwrap();
(erc1155, erc1155_id.into())
}
pub async fn post_setup(
strategy: Strategy<WalletUnlocked>,
royalty_manager: RoyaltyManager<WalletUnlocked>,
thunder_exchange: ThunderExchange<WalletUnlocked>,
execution_manager: ExecutionManager<WalletUnlocked>,
asset_manager: AssetManager<WalletUnlocked>,
pool_id: ContractId,
protocol_fee_recipient: Address,
nft_holder: Address
) {
strategy.methods().set_protocol_fee(STRATEGY_FEE).call().await.unwrap();
royalty_manager.methods().set_royalty_fee_limit(ROYALTY_MANAGER_FEE_LIMIT).call().await.unwrap();
thunder_exchange.methods().set_pool(pool_id).call().await.unwrap();
thunder_exchange.methods().set_execution_manager(execution_manager.id()).call().await.unwrap();
thunder_exchange.methods().set_royalty_manager(royalty_manager.id()).call().await.unwrap();
thunder_exchange.methods().set_asset_manager(asset_manager.id()).call().await.unwrap();
thunder_exchange.methods().set_protocol_fee_recipient(Identity::Address(protocol_fee_recipient)).call().await.unwrap();
execution_manager.methods()
.add_strategy(strategy.id())
.call()
.await
.unwrap();
asset_manager.methods()
.add_asset(BASE_ASSET)
.call()
.await
.unwrap();
}
async fn get_contract_instances() -> (
Accounts,
(AssetManager<WalletUnlocked>, ContractId),
(ExecutionManager<WalletUnlocked>, ContractId),
(ThunderExchange<WalletUnlocked>, ContractId),
(Pool<WalletUnlocked>, ContractId),
(RoyaltyManager<WalletUnlocked>, ContractId),
(Strategy<WalletUnlocked>, ContractId),
(ERC1155<WalletUnlocked>, ContractId)
) {
let accounts = get_wallets().await;
let (asset_manager, asset_manager_id) = setup_asset_manager(accounts[0].clone()).await;
let (execution_manager, execution_manager_id) = setup_execution_manager(accounts[0].clone()).await;
let (thunder_exchange, thunder_exchange_id) = setup_thunder_exchange(accounts[0].clone()).await;
let (pool, pool_id) = setup_pool(accounts[0].clone(), thunder_exchange_id, asset_manager_id).await;
let (royalty_manager, royalty_manager_id) = setup_royalty_manager(accounts[0].clone()).await;
let (strategy, strategy_id) = setup_strategy(accounts[0].clone(), thunder_exchange_id).await;
let (erc1155, erc1155_id) = setup_erc1155(accounts[0].clone(), accounts[1].address().into()).await;
post_setup(
strategy.clone(),
royalty_manager.clone(),
thunder_exchange.clone(),
execution_manager.clone(),
asset_manager.clone(),
pool_id,
accounts[4].address().into(),
accounts[1].address().into()
).await;
(
accounts,
(asset_manager, asset_manager_id),
(execution_manager, execution_manager_id),
(thunder_exchange, thunder_exchange_id),
(pool, pool_id),
(royalty_manager, royalty_manager_id),
(strategy, strategy_id),
(erc1155, erc1155_id)
)
}
/////////////////////////////////////Setup End/////////////////////////////////////
/////////////////////////////////////POC/////////////////////////////////////
#[tokio::test]
async fn test_poc() {
let (
[_owner, alice, bob, _protocol_fee_recipient, _user],
(_asset_manager, asset_manager_id),
(_execution_manager, execution_manager_id),
(thunder_exchange, _thunder_exchange_id),
(_pool, pool_id),
(_royalty_manager, royalty_manager_id),
(strategy, strategy_id),
(erc1155, erc1155_id)
) = get_contract_instances().await;
let ERC1155_NFT = AssetId::from_str(ERC1155_NFT_STR).unwrap();
let thunder_exchange_alice = thunder_exchange.clone().with_account(alice.clone());
let thunder_exchange_bob = thunder_exchange.clone().with_account(bob.clone());
erc1155.methods() //10 ERC1155 tokens are minted for alice so she can sell them
.mint(alice.address().into(), Bits256::zeroed(), 10)
.append_variable_outputs(1)
.call()
.await
.unwrap();
//The order for alice so that she can sell her 10 tokens for a price of 800
let maker_order_input = MakerOrderInput {
maker: alice.address().into(),
collection: erc1155_id.clone(),
price: 800,
amount: 10,
nonce: 1,
strategy: strategy_id,
payment_asset: BASE_ASSET,
expiration_range: 10000,
token_id: Bits256::zeroed(),
side: Side::Sell,
extra_params: ExtraParams {
extra_address_param: Address::zeroed(),
extra_contract_param: ContractId::zeroed(),
extra_u_64_param: 0
}
};
//Alice places the sell order created above on the thunder exchange and sends the 10 ERC1155 tokens which are then in the contract
thunder_exchange_alice.methods()
.place_order(maker_order_input)
.call_params(CallParameters::new(10, ERC1155_NFT, 1_000_000))
.unwrap()
.append_contract(execution_manager_id.into())
.append_contract(strategy_id.into())
.append_contract(pool_id.into())
.append_contract(asset_manager_id.into())
.call()
.await
.unwrap();
println!("------------Alice sells 10 ERC1155 tokens--------------");
println!("alice sell order: {:#?}", strategy.methods().get_maker_order_of_user(alice.address(), 1, Side::Sell).call().await.unwrap().value);
//This is the taker order from bob with which he buys the 10 erc1155 tokens for 800.
let taker_order = TakerOrder {
side: Side::Buy,
taker: bob.address().into(),
maker: alice.address().into(),
nonce: 1,
price: 800,
token_id: Bits256::zeroed(),
collection: erc1155_id.clone(),
strategy: strategy_id.clone(),
extra_params: ExtraParams {
extra_address_param: Address::zeroed(),
extra_contract_param: ContractId::zeroed(),
extra_u_64_param: 0
}
};
//Bob executed the orders and sends his 800 tokens but he will only get one of the 1 of the 10 ERC1155 NFTs
thunder_exchange_bob.methods()
.execute_order(taker_order)
.call_params(CallParameters::new(800, BASE_ASSET, 1_000_000))
.unwrap()
.append_contract(execution_manager_id.into())
.append_contract(strategy_id.into())
.append_contract(pool_id.into())
.append_contract(asset_manager_id.into())
.append_contract(royalty_manager_id.into())
.append_variable_outputs(3)
.call()
.await
.unwrap();
//This shows that Bob received only one NFT and paid the full price. The other NFTs are now stuck in Thunder Exchange because the order is no longer there
println!("bob balance ERC1155 NFT: {:#?}", bob.get_asset_balance(&ERC1155_NFT).await.unwrap());
println!("bob balance BASE_ASSET: {:#?}", bob.get_asset_balance(&BASE_ASSET).await.unwrap()); //Bob had 1000000000 at the beginning, now he should only have 999999200
println!("order (not existent): {:#?}", strategy.methods() //shows that the order was really deleted
.get_maker_order_of_user(alice.address(), 1, Side::Sell)
.call()
.await
.unwrap()
.value
);
}