Compute edges from safes.
This commit is contained in:
parent
a7e9aefd40
commit
5969204a1f
3 changed files with 129 additions and 5 deletions
|
@ -1,16 +1,60 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, default};
|
||||
|
||||
use crate::types::{Address, Safe};
|
||||
use crate::types::{edge::EdgeDB, Address, Edge, Safe, U256};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct DB {
|
||||
safes: BTreeMap<Address, Safe>,
|
||||
token_owner: BTreeMap<Address, Address>,
|
||||
edges: EdgeDB,
|
||||
}
|
||||
|
||||
impl DB {
|
||||
pub fn new(safes: BTreeMap<Address, Safe>, token_owner: BTreeMap<Address, Address>) -> DB {
|
||||
println!("{} safes, {} tokens", safes.len(), token_owner.len());
|
||||
DB { safes, token_owner }
|
||||
let mut db = DB {
|
||||
safes,
|
||||
token_owner,
|
||||
..Default::default()
|
||||
};
|
||||
db.compute_edges();
|
||||
db
|
||||
}
|
||||
|
||||
fn compute_edges(&mut self) {
|
||||
let mut edges = vec![];
|
||||
for (user, safe) in &self.safes {
|
||||
// trust connections
|
||||
for (send_to, percentage) in &safe.limit_percentage {
|
||||
if *user == *send_to {
|
||||
continue;
|
||||
}
|
||||
if let Some(receiver_safe) = self.safes.get(send_to) {
|
||||
let limit = safe.trust_transfer_limit(receiver_safe, *percentage);
|
||||
if limit != U256::from(0) {
|
||||
edges.push(Edge {
|
||||
from: *user,
|
||||
to: *send_to,
|
||||
token: *user,
|
||||
capacity: limit,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
// send tokens back to owner
|
||||
for (token, balance) in &safe.balances {
|
||||
if let Some(owner) = self.token_owner.get(token) {
|
||||
if *user != *owner {
|
||||
edges.push(Edge {
|
||||
from: *user,
|
||||
to: *owner,
|
||||
token: *owner,
|
||||
capacity: *balance,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.edges = EdgeDB::new(edges)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::{cmp::min, collections::BTreeMap};
|
||||
|
||||
use super::{Address, U256};
|
||||
|
||||
|
@ -10,3 +10,26 @@ pub struct Safe {
|
|||
pub limit_percentage: BTreeMap<Address, u8>,
|
||||
pub organization: bool,
|
||||
}
|
||||
|
||||
impl Safe {
|
||||
pub fn balance(&self, token: &Address) -> U256 {
|
||||
*self.balances.get(token).unwrap_or(&U256::from(0))
|
||||
}
|
||||
/// @returns how much of their own tokens a user can send to receiver.
|
||||
pub fn trust_transfer_limit(&self, receiver: &Safe, trust_percentage: u8) -> U256 {
|
||||
if receiver.organization {
|
||||
// TODO treat this as "return to owner"
|
||||
self.balance(&self.token_address)
|
||||
} else {
|
||||
let receiver_balance = receiver.balance(&self.token_address);
|
||||
let amount = (receiver.balance(&receiver.token_address)
|
||||
* U256::from(trust_percentage as u128))
|
||||
/ U256::from(100);
|
||||
if amount < receiver_balance {
|
||||
U256::from(0)
|
||||
} else {
|
||||
min(amount - receiver_balance, self.balance(&self.token_address))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::fmt::Debug;
|
||||
use std::fmt::Display;
|
||||
use std::fmt::Formatter;
|
||||
use std::ops::Div;
|
||||
use std::ops::Mul;
|
||||
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
|
||||
|
||||
use num_bigint::BigUint;
|
||||
|
@ -13,12 +15,22 @@ impl U256 {
|
|||
U256([high, low])
|
||||
}
|
||||
pub const MAX: U256 = U256::new(u128::MAX, u128::MAX);
|
||||
pub fn from_bigint_truncating(input: BigUint) -> U256 {
|
||||
let digits = input.to_u64_digits();
|
||||
U256([
|
||||
u128::from(*digits.get(3).unwrap_or(&0)) << 64
|
||||
| u128::from(*digits.get(2).unwrap_or(&0)),
|
||||
u128::from(*digits.get(1).unwrap_or(&0)) << 64
|
||||
| u128::from(*digits.first().unwrap_or(&0)),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn to_decimal(self) -> String {
|
||||
let value = BigUint::from(self.0[0]) << 128 | BigUint::from(self.0[1]);
|
||||
format!("{value}")
|
||||
}
|
||||
pub fn to_decimal_fraction(self) -> String {
|
||||
let value = BigUint::from(self.0[0]) << 128 | BigUint::from(self.0[1]);
|
||||
let value: BigUint = self.into();
|
||||
let formatted = format!("{value}");
|
||||
match formatted.len() {
|
||||
18.. => {
|
||||
|
@ -85,6 +97,12 @@ impl From<&str> for U256 {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<U256> for BigUint {
|
||||
fn from(value: U256) -> Self {
|
||||
BigUint::from(value.0[0]) << 128 | BigUint::from(value.0[1])
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for U256 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
|
@ -118,6 +136,26 @@ impl Sub for U256 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Mul for U256 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
let self_big: BigUint = self.into();
|
||||
let rhs_big: BigUint = rhs.into();
|
||||
U256::from_bigint_truncating(self_big * rhs_big)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for U256 {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
let self_big: BigUint = self.into();
|
||||
let rhs_big: BigUint = rhs.into();
|
||||
U256::from_bigint_truncating(self_big / rhs_big)
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for U256 {
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
*self = *self - rhs;
|
||||
|
@ -222,4 +260,23 @@ mod test {
|
|||
"340282366920938463463374607431768211456"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_mul_div() {
|
||||
let two = U256::from("2");
|
||||
let three = U256::from(3);
|
||||
let large = U256::from("0x100000000000000000000000000000000");
|
||||
assert_eq!(two * three, U256::from(6));
|
||||
assert_eq!(three / two, U256::from(1));
|
||||
assert_eq!((large * two) / two, large);
|
||||
assert_eq!(
|
||||
large / three,
|
||||
U256::from("0x55555555555555555555555555555555")
|
||||
);
|
||||
assert_eq!(large * large, U256::from("0"));
|
||||
assert_eq!(
|
||||
(large / two) * large,
|
||||
U256::from("0x8000000000000000000000000000000000000000000000000000000000000000")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue