Skip to content

Commit

Permalink
Added pallet-share_distributor, necessary to complete pallet bidding
Browse files Browse the repository at this point in the history
  • Loading branch information
ndkazu committed Oct 19, 2023
1 parent ac05849 commit b0ddcda
Show file tree
Hide file tree
Showing 8 changed files with 732 additions and 80 deletions.
191 changes: 117 additions & 74 deletions Cargo.lock

Large diffs are not rendered by default.

66 changes: 63 additions & 3 deletions pallets/share_distributor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,68 @@
[package]
name = "share_distributor"
version = "0.1.0"
name = "pallet-share_distributor"
version = "4.0.0-dev"
description = "Distribute to the asset new owners/contributors, the ownership nft, and the ownership token"
authors = ["Fair Squares"]
homepage = "https://fair-squares.nl"
edition = "2021"
license = "Apache 2.0"
publish = false
repository = "https://github.com/Fair-Squares/fair-squares"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
enum-iterator = "1.4.1"
num-traits = {version="0.2.17",default-features = false}
sp-arithmetic = {version="19.0.0",default-features = false}
codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [
"derive",
] }
sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
scale-info = { version = "2.9.0", default-features = false, features = ["derive"] }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
sp-std = { default-features = false, version = "8.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
pallet-assets = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
pallet-sudo = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
serde = { version = "1.0.183", default-features = false, features = ["derive"] }
pallet-roles = { default-features = false, path="../roles" }
pallet-onboarding = { default-features = false, path="../onboarding" }
pallet-housing_fund = { default-features = false, path="../housing_fund" }
pallet-nft = { default-features = false, path="../nft" }

[dev-dependencies]
sp-core = { version = "21.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
sp-io = { version = "23.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }
sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" }

[features]
default = ["std"]
std = [
"codec/std",
"frame-benchmarking/std",
"sp-std/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
"serde/std",
"sp-std/std",
"pallet-balances/std",
"pallet-sudo/std",
"pallet-roles/std",
"pallet-onboarding/std",
"pallet-nft/std",
"pallet-housing_fund/std",
"pallet-assets/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
]

try-runtime = [
"frame-support/try-runtime",
]
230 changes: 230 additions & 0 deletions pallets/share_distributor/src/functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
use super::*;
use enum_iterator::all;
#[allow(unused_imports)]
use num_traits::float::FloatCore;
use sp_runtime::{traits::SaturatedConversion, FixedPointNumber, FixedU128};

impl<T: Config> Pallet<T> {

pub fn virtual_account(
collection_id: T::NftCollectionId,
item_id: T::NftItemId,
) -> DispatchResult {
//Create virtual account
let text0 = format!("{collection_id:?}_{:?}_account", item_id.clone());
let bytes = text0.as_bytes();
let array: &[u8; 8] = &bytes[0..8].try_into().unwrap();
let account: T::AccountId = PalletId(*array).into_account_truncating();

//Store account inside storage
Ownership::<T>::new(collection_id, item_id, account.clone()).ok();
Owners::<T>::new(account.clone()).ok();

//The virtual account needs some initial funds to pay for asset creation fees
//These funds could be provided by the FairSquare FeesAccount maintained in the
//Onboarding pallet.
let fees_account = Onboarding::Pallet::<T>::account_id();
let fees = T::Fees::get();
//Ensure that we have enough money in the fees_account
let balance = <T as Roles::Config>::Currency::free_balance(&fees_account);
ensure!(fees < balance, Error::<T>::NotEnoughFees);

let res = <T as Roles::Config>::Currency::transfer(
&fees_account,
&account,
fees,
ExistenceRequirement::AllowDeath,
);
debug_assert!(res.is_ok());

Ok(())
}

///This function executes all actions relatives to nft transfer from the seller to the virtual
/// account
pub fn nft_transaction(
collection_id: T::NftCollectionId,
item_id: T::NftItemId,
virtual_id: T::AccountId,
) -> DispatchResult {
//Get collection
let collection_vec = all::<Nft::PossibleCollections>().collect::<Vec<_>>();
let _infos = Onboarding::Houses::<T>::get(collection_id, item_id).unwrap();
let mut coll_id = Nft::PossibleCollections::HOUSES;
for i in collection_vec.iter() {
let val: T::NftCollectionId = i.value().into();
if val == collection_id {
coll_id = *i;
}
}
//Execute NFT and money transfer
Onboarding::Pallet::do_buy(coll_id, item_id, virtual_id, _infos).ok();

Ok(())
}

///Collect contributors to the bid, and their shares
pub fn owner_and_shares(
collection_id: T::NftCollectionId,
item_id: T::NftItemId,
_total_tokens: <T as Assets::Config>::Balance,
) -> Vec<(T::AccountId, u128)> {
//Get owners and their reserved contribution to the bid

let reservation_infos =
HousingFund::Reservations::<T>::get((collection_id, item_id)).unwrap();
let vec0 = reservation_infos.contributions;
let price = reservation_infos.amount;
let virtual_acc = Self::virtual_acc(collection_id, item_id).unwrap().virtual_account;

let mut vec = Vec::new();
for i in vec0.iter() {
let price0 = Self::hfund_bal_to_u128(price).unwrap();
let contribution0 = Self::hfund_bal_to_u128(i.1).unwrap();

let price1 = Self::balance_to_f64_option0(price).unwrap();
let contribution1 = Self::balance_to_f64_option0(i.1).unwrap();
let frac = (contribution1 / price1).round();
let mut share = FixedU128::saturating_from_rational(contribution0, price0)
.saturating_mul_int(1000u128);
let fl = share as f64;
if (fl + 0.5) < frac {
share += 1;
}

debug_assert!(share < 1000);
debug_assert!(share > 0);

vec.push((i.0.clone(), share));
//Update Virtual_account storage
let mut val0 = Self::virtual_acc(collection_id,item_id).unwrap();
let _=val0.owners.try_push(i.0.clone());
Virtual::<T>::mutate(collection_id, item_id, |val| {

*val = Some(val0);
});
let amount: <T as Assets::Config>::Balance =
share.saturated_into::<<T as Assets::Config>::Balance>();
let mut val0 = Self::tokens_infos(virtual_acc.clone()).unwrap();
//Update owners in Tokens storage
Tokens::<T>::mutate(&virtual_acc, |val| {

let _=val0.owners.try_push((i.0.clone(), amount));
*val = Some(val0);
});
}
vec
}

///Create 1000 Ownership tokens owned by a virtual account
pub fn create_tokens(
origin: OriginFor<T>,
collection_id: T::NftCollectionId,
item_id: T::NftItemId,
account: T::AccountId,
) -> DispatchResult {
//Get token class Id:
ensure!(Virtual::<T>::get(collection_id, item_id).is_some(), Error::<T>::InvalidValue);
let token_id = Virtual::<T>::get(collection_id, item_id).unwrap().token_id;
let to = T::Lookup::unlookup(account.clone());
TokenId::<T>::mutate(|val| {
let val0 = *val;
*val = val0 + 1;
});

//Create token class
let res = Assets::Pallet::<T>::force_create(
origin.clone(),
token_id.into(),
to.clone(),
true,
One::one(),
);
debug_assert!(res.is_ok());

//Set class metadata
let token_name = format!("FairOwner_nbr{:?}", token_id.clone()).as_bytes().to_vec();
let token_symbol = format!("FO{:?}", token_id.clone()).as_bytes().to_vec();
let decimals = 1;
Assets::Pallet::<T>::force_set_metadata(
origin,
token_id.into(),
token_name,
token_symbol,
decimals,
false,
)
.ok();

//mint 1000 tokens
let res0 = Assets::Pallet::<T>::mint(
RawOrigin::Signed(account.clone()).into(),
token_id.into(),
to,
Self::u32_to_balance_option(1000).unwrap(),
);
debug_assert!(res0.is_ok());
let mut val0 = Self::tokens_infos(account.clone()).unwrap();
//Update supply in Tokens storage
Tokens::<T>::mutate(account, |val| {

val0.supply = Assets::Pallet::<T>::total_supply(token_id.into());
*val = Some(val0);
});

Ok(())
}

///Distribute the ownership tokens to the group of new owners
pub fn distribute_tokens(
account: T::AccountId,
collection_id: T::NftCollectionId,
item_id: T::NftItemId,
) -> DispatchResult {
ensure!(Virtual::<T>::get(collection_id, item_id).is_some(), Error::<T>::InvalidValue);
let token_id = Virtual::<T>::get(collection_id, item_id).unwrap().token_id;
let total_tokens = Assets::Pallet::<T>::total_supply(token_id.into());
debug_assert!(total_tokens == Self::u32_to_balance_option(1000).unwrap());
let shares = Self::owner_and_shares(collection_id, item_id, total_tokens);

let from = T::Lookup::unlookup(account.clone());
let origin: OriginFor<T> = RawOrigin::Signed(account).into();

for share in shares.iter() {
let amount0 = share.clone().1;
debug_assert!(amount0 > 0);
let amount: <T as Assets::Config>::Balance =
share.clone().1.saturated_into::<<T as Assets::Config>::Balance>();
debug_assert!(!amount.clone().is_zero());
let to = T::Lookup::unlookup(share.clone().0);
Assets::Pallet::<T>::force_transfer(
origin.clone(),
token_id.into(),
from.clone(),
to,
amount,
)
.ok();
}

Ok(())
}

// Conversion of u32 to Balance
pub fn u32_to_balance_option(input: u32) -> Option<T::Balance> {
input.try_into().ok()
}

// Conversion of BalanceOf<T> to u128
pub fn hfund_bal_to_u128(input: HousingFund::BalanceOf<T>) -> Option<u128> {
input.try_into().ok()
}

// Conversion of BalanceOf<T> to f64
pub fn balance_to_f64_option0(input: HousingFund::BalanceOf<T>) -> Option<f64> {
let integer: u64 = input.try_into().ok().unwrap();
let float = integer as f64;
Some(float)
}

}
Loading

0 comments on commit b0ddcda

Please sign in to comment.