Skip to content
This repository has been archived by the owner on May 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #6 from Cerebellum-Network/splitfile
Browse files Browse the repository at this point in the history
Split file
  • Loading branch information
naure authored Feb 25, 2022
2 parents f2fbe87 + 560b964 commit bd29080
Show file tree
Hide file tree
Showing 23 changed files with 768 additions and 509 deletions.
78 changes: 78 additions & 0 deletions bucket/ddc_bucket/account/entity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use ink_storage::traits::{PackedLayout, SpreadLayout};
use scale::{Decode, Encode};

use crate::ddc_bucket::{
Balance, cash::{Cash, Payable},
Error::*, Result,
schedule::Schedule,
};

#[derive(PartialEq, Encode, Decode, SpreadLayout, PackedLayout)]
#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))]
pub struct Account {
pub deposit: Cash,
pub payable_locked: Balance,
pub payable_schedule: Schedule,
}

impl Account {
pub fn new() -> Account {
Account {
deposit: Cash(0),
payable_locked: 0,
payable_schedule: Schedule::empty(),
}
}

pub fn deposit(&mut self, cash: Cash) {
self.deposit.increase(cash);
}

pub fn withdraw(&mut self, time_ms: u64, payable: Payable) -> Result<()> {
if self.get_withdrawable(time_ms) >= payable.peek() {
self.deposit.pay_unchecked(payable);
Ok(())
} else {
Err(InsufficientBalance)
}
}

pub fn get_withdrawable(&self, time_ms: u64) -> Balance {
let deposit = self.deposit.peek();
let consumed = self.payable_locked + self.payable_schedule.value_at_time(time_ms);
if deposit >= consumed {
deposit - consumed
} else {
0
}
}

pub fn lock_schedule(&mut self, payable_schedule: Schedule) {
let more_locked = self.payable_schedule.take_value_then_add_rate(payable_schedule);
self.payable_locked += more_locked;
}

pub fn schedule_covered_until(&self) -> u64 {
self.payable_schedule.time_of_value(self.deposit.peek())
}

pub fn pay_scheduled(&mut self, now_ms: u64, payable: Payable) -> Result<()> {
self.unlock_scheduled_amount(now_ms, payable.peek());
self.pay(payable)
}

fn pay(&mut self, payable: Payable) -> Result<()> {
if self.deposit.peek() >= payable.peek() {
self.deposit.pay_unchecked(payable);
Ok(())
} else {
Err(InsufficientBalance)
}
}

fn unlock_scheduled_amount(&mut self, now_ms: u64, unlocked: Balance) {
self.payable_locked = self.payable_locked
+ self.payable_schedule.take_value_at_time(now_ms)
- unlocked;
}
}
2 changes: 2 additions & 0 deletions bucket/ddc_bucket/account/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod entity;
pub mod store;
46 changes: 46 additions & 0 deletions bucket/ddc_bucket/account/store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use ink_storage::{
collections::{HashMap, hashmap::Entry::*},
traits,
};

use crate::ddc_bucket::{
AccountId, Balance, cash::Cash, Error::*,
Result,
};

use super::entity::Account;

#[derive(traits::SpreadLayout, Default)]
#[cfg_attr(feature = "std", derive(traits::StorageLayout, Debug))]
pub struct AccountStore(pub HashMap<AccountId, Account>);

impl AccountStore {
pub fn deposit(&mut self, to: AccountId, cash: Cash) {
match self.0.entry(to) {
Vacant(e) => {
let mut account = Account::new();
account.deposit(cash);
e.insert(account);
}
Occupied(mut e) => {
let account = e.get_mut();
account.deposit(cash);
}
};
}

pub fn balance(&self, account_id: &AccountId) -> Balance {
match self.0.get(account_id) {
None => 0,
Some(account) => account.deposit.peek(),
}
}

pub fn get(&self, account_id: &AccountId) -> Result<&Account> {
self.0.get(account_id).ok_or(AccountDoesNotExist)
}

pub fn get_mut(&mut self, account_id: &AccountId) -> Result<&mut Account> {
self.0.get_mut(account_id).ok_or(AccountDoesNotExist)
}
}
83 changes: 83 additions & 0 deletions bucket/ddc_bucket/billing/messages.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use ink_lang::{EmitEvent, StaticEnv};

use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, Deposit, FlowId, InsufficientBalance, Payable, Result, Schedule};

impl DdcBucket {
pub fn message_deposit(&mut self) -> Result<()> {
// Receive the payable value.
let cash = Self::receive_cash();
let value = cash.peek();
let account_id = Self::env().caller();

self.accounts.deposit(account_id, cash);
Self::env().emit_event(Deposit { account_id, value });
Ok(())
}

pub fn billing_withdraw(&mut self, from: AccountId, payable: Payable) -> Result<()> {
let account = self.accounts.0.get_mut(&from)
.ok_or(InsufficientBalance)?;

let time_ms = Self::env().block_timestamp();
account.withdraw(time_ms, payable)?;
Ok(())
}

pub fn billing_get_net(&self, from: AccountId) -> Balance {
match self.accounts.0.get(&from) {
None => 0,
Some(account) => {
let time_ms = Self::env().block_timestamp();
account.get_withdrawable(time_ms)
}
}
}

pub fn billing_transfer(&mut self, from: AccountId, to: AccountId, amount: Balance) -> Result<()> {
let (payable, cash) = Cash::borrow_payable_cash(amount);
self.billing_withdraw(from, payable)?;
self.accounts.deposit(to, cash);
Ok(())
}

pub fn billing_start_flow(&mut self, from: AccountId, rate: Balance) -> Result<FlowId> {
let start_ms = Self::env().block_timestamp();
let cash_schedule = Schedule::new(start_ms, rate);
let payable_schedule = cash_schedule.clone();

let from_account = self.accounts.get_mut(&from)?;
from_account.lock_schedule(payable_schedule);

let flow_id = self.flows.create(from, cash_schedule);
Ok(flow_id)
}

pub fn billing_flow_covered_until(&self, flow_id: FlowId) -> Result<u64> {
let flow = self.flows.get(flow_id)?;
let account = self.accounts.get(&flow.from)?;
Ok(account.schedule_covered_until())
}

pub fn billing_settle_flow(&mut self, flow_id: FlowId) -> Result<Cash> {
let now_ms = Self::env().block_timestamp();

let flow = self.flows.get_mut(flow_id)?;
let flowed_amount = flow.schedule.take_value_at_time(now_ms);
let (payable, cash) = Cash::borrow_payable_cash(flowed_amount);

let account = self.accounts.get_mut(&flow.from)?;
account.pay_scheduled(now_ms, payable)?;
Ok(cash)
}

pub fn receive_cash() -> Cash {
Cash(Self::env().transferred_balance())
}

pub fn send_cash(destination: AccountId, cash: Cash) -> Result<()> {
match Self::env().transfer(destination, cash.consume()) {
Err(_e) => panic!("Transfer failed"), // Err(Error::TransferFailed),
Ok(_v) => Ok(()),
}
}
}
1 change: 1 addition & 0 deletions bucket/ddc_bucket/billing/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod messages;
37 changes: 37 additions & 0 deletions bucket/ddc_bucket/bucket/entity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use ink_prelude::{
string::String,
vec::Vec,
};
use ink_storage::traits::{PackedLayout, SpreadLayout};
use scale::{Decode, Encode};

use crate::ddc_bucket::{
AccountId, deal::entity::{DealId, DealStatus}, Error::*,
Result,
};

pub type BucketId = u32;
pub type BucketParams = String;

#[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)]
#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))]
pub struct Bucket {
pub owner_id: AccountId,
pub deal_ids: Vec<DealId>,
pub bucket_params: BucketParams,
}

#[derive(Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))]
pub struct BucketStatus {
pub bucket_id: BucketId,
pub bucket: Bucket,
pub writer_ids: Vec<AccountId>,
pub deal_statuses: Vec<DealStatus>,
}

impl Bucket {
pub fn only_owner(&self, caller: AccountId) -> Result<()> {
if self.owner_id == caller { Ok(()) } else { Err(UnauthorizedOwner) }
}
}
69 changes: 69 additions & 0 deletions bucket/ddc_bucket/bucket/messages.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use ink_lang::{EmitEvent, StaticEnv};
use ink_prelude::{vec, vec::Vec};

use crate::ddc_bucket::{AccountId, BucketCreated, DdcBucket, DealCreated, DealId, DealParams, Result, ServiceId};

use super::entity::{Bucket, BucketId, BucketParams, BucketStatus};

impl DdcBucket {
pub fn message_bucket_create(&mut self, bucket_params: BucketParams) -> Result<BucketId> {
let owner_id = Self::env().caller();
let bucket_id = self.buckets.create(owner_id, bucket_params);
Self::env().emit_event(BucketCreated { bucket_id, owner_id });
Ok(bucket_id)
}

pub fn message_bucket_add_deal(&mut self, bucket_id: BucketId, service_id: ServiceId, deal_params: DealParams) -> Result<DealId> {
// Receive the payable value.
self.deposit()?;
let owner_id = Self::env().caller();

let deal_id = self.deal_create(service_id, deal_params)?;

let bucket = self.buckets.get_mut(bucket_id)?;
bucket.only_owner(owner_id)?;
bucket.deal_ids.push(deal_id);

Self::env().emit_event(DealCreated { deal_id, bucket_id, service_id });
Ok(deal_id)
}

pub fn message_bucket_list_statuses(&self, offset: u32, limit: u32, filter_owner_id: Option<AccountId>) -> (Vec<BucketStatus>, u32) {
let mut bucket_statuses = Vec::with_capacity(limit as usize);
for bucket_id in offset..offset + limit {
let bucket = match self.buckets.0.get(bucket_id) {
None => break, // No more buckets, stop.
Some(bucket) => bucket,
};
// Apply the filter if given.
if let Some(owner_id) = filter_owner_id {
if owner_id != bucket.owner_id {
continue; // Skip non-matches.
}
}
// Collect all the details of the bucket.
match self.bucket_collect_status(bucket_id, bucket.clone()) {
Err(_) => continue, // Skip on unexpected error.
Ok(status) =>
bucket_statuses.push(status),
};
}
(bucket_statuses, self.buckets.0.len())
}

pub fn message_bucket_get_status(&self, bucket_id: BucketId) -> Result<BucketStatus> {
let bucket = self.bucket_get(bucket_id)?;
self.bucket_collect_status(bucket_id, bucket)
}

pub fn bucket_collect_status(&self, bucket_id: BucketId, bucket: Bucket) -> Result<BucketStatus> {
let writer_ids = vec![bucket.owner_id];

let mut deal_statuses = Vec::with_capacity(bucket.deal_ids.len());
for deal_id in bucket.deal_ids.iter() {
deal_statuses.push(self.deal_get_status(*deal_id)?);
}

Ok(BucketStatus { bucket_id, bucket, writer_ids, deal_statuses })
}
}
3 changes: 3 additions & 0 deletions bucket/ddc_bucket/bucket/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod entity;
pub mod store;
pub mod messages;
34 changes: 34 additions & 0 deletions bucket/ddc_bucket/bucket/store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use ink_prelude::vec::Vec;
use ink_storage::{
collections::Vec as InkVec,
traits,
};

use crate::ddc_bucket::{AccountId, Error::*, Result};

use super::entity::{Bucket, BucketId, BucketParams};

#[derive(traits::SpreadLayout, Default)]
#[cfg_attr(feature = "std", derive(traits::StorageLayout, Debug))]
pub struct BucketStore(pub InkVec<Bucket>);

impl BucketStore {
pub fn create(&mut self, owner_id: AccountId, bucket_params: BucketParams) -> BucketId {
let bucket = Bucket {
owner_id,
deal_ids: Vec::new(),
bucket_params,
};
let bucket_id = self.0.len();
self.0.push(bucket);
bucket_id
}

pub fn get(&self, bucket_id: BucketId) -> Result<&Bucket> {
self.0.get(bucket_id).ok_or(BucketDoesNotExist)
}

pub fn get_mut(&mut self, bucket_id: BucketId) -> Result<&mut Bucket> {
self.0.get_mut(bucket_id).ok_or(BucketDoesNotExist)
}
}
Loading

0 comments on commit bd29080

Please sign in to comment.