Skip to content

Commit

Permalink
value into tokens then multiply then tokens into value
Browse files Browse the repository at this point in the history
  • Loading branch information
logicalmechanism committed Jan 26, 2024
1 parent db6ad22 commit 38b0ddf
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 12 deletions.
45 changes: 45 additions & 0 deletions lib/assist/types/token.ak
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//// instead of building out the value type directly which could be harmful.
////

use aiken/dict
use aiken/list
use aiken/transaction/value.{AssetName, PolicyId, Value}

Expand Down Expand Up @@ -239,3 +240,47 @@ test add_and_subtract_tokens_to_value() {
let token2: Token = Token { pid: #"", tkn: #"", amt: -10 }
add_tokens_to_value(zero, [token1, token2]) == zero
}

/// Convert a value into a list of tokens. This conversation is a fast way
/// to be able to do multiplication on a value.
///
/// ```aiken
/// token.from_value(this_value)
/// ```
pub fn from_value(v: Value) -> Tokens {
value.to_dict(v)
|> dict.foldl(
[],
fn(pid, assets, tokens) {
dict.foldl(
assets,
tokens,
fn(tkn, amt, tokens) { list.push(tokens, Token { pid, tkn, amt }) },
)
},
)
}

test from_zero_value() {
let v: Value = value.zero()
let e: Tokens =
[]
from_value(v) == e
}

test from_lovelace_value() {
let v: Value = value.from_lovelace(123)
let e: Tokens =
[Token { pid: value.ada_policy_id, tkn: value.ada_asset_name, amt: 123 }]
from_value(v) == e
}

test from_general_value() {
let v: Value = value.from_lovelace(123) |> value.add(#"acab", #"cafe", 41)
let e: Tokens =
[
Token { pid: #"acab", tkn: #"cafe", amt: 41 },
Token { pid: value.ada_policy_id, tkn: value.ada_asset_name, amt: 123 },
]
from_value(v) == e
}
41 changes: 29 additions & 12 deletions lib/assist/values.ak
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,36 @@ fn do_from_tokens(val: Value, tokens: Tokens) -> Value {
}
}

test from_value_then_multiply_back_to_value() {
let v: Value = value.from_lovelace(2)
let ts: Tokens = token.from_value(v)
let n: Int = 52314523
let ans: Value = product([], ts, n) |> from_tokens()
let exp: Value = value.from_lovelace(104629046)
ans == exp
}

fn product(ans: Tokens, ts: Tokens, n: Int) -> Tokens {
when ts is {
// take a token and add it to the value
[tkn, ..tkns] ->
ans
|> list.push(Token { pid: tkn.pid, tkn: tkn.tkn, amt: n * tkn.amt })
|> product(tkns, n)
// everything is negative
[] -> ans
}
}

/// Multiply some value by `n`. This is just a linear scaling to the quantity
/// of each token.
///
/// ```aiken
/// values.multiply(bundle_value, bundle_size)
/// ```
pub fn multiply(val: Value, n: Int) -> Value {
do_multiply(value.zero(), val, n)
}

// Internal only
fn do_multiply(total: Value, add_val: Value, n: Int) -> Value {
// 4 * v = v + v + v + v
if n <= 0 {
total
} else {
// add to total
do_multiply(value.merge(total, add_val), add_val, n - 1)
}
let ts: Tokens = token.from_value(val)
product([], ts, n) |> from_tokens()
}

test values_multiply_by_0() {
Expand All @@ -85,6 +96,12 @@ test values_multiply_by_4() {
multiply(val, 4) == ans
}

test values_multiply_by_52314523() {
let val: Value = value.from_lovelace(2)
let ans: Value = value.from_lovelace(104629046)
multiply(val, 52314523) == ans
}

/// Prove that the target value is contained inside another value. Each token
/// inside the target must exist inside the total value. The quantity of each
/// token must be at least the target amount or greater.
Expand Down

0 comments on commit 38b0ddf

Please sign in to comment.