diff --git a/frameworks/bitcoin-move/doc/bitcoin.md b/frameworks/bitcoin-move/doc/bitcoin.md index 7ab19ea82d..6ad8d52dfd 100644 --- a/frameworks/bitcoin-move/doc/bitcoin.md +++ b/frameworks/bitcoin-move/doc/bitcoin.md @@ -8,7 +8,8 @@ - [Struct `UTXONotExistsEvent`](#0x4_bitcoin_UTXONotExistsEvent) - [Struct `RepeatCoinbaseTxEvent`](#0x4_bitcoin_RepeatCoinbaseTxEvent) - [Resource `BitcoinBlockStore`](#0x4_bitcoin_BitcoinBlockStore) -- [Struct `TransferUTXOEvent`](#0x4_bitcoin_TransferUTXOEvent) +- [Struct `SpendUTXOEvent`](#0x4_bitcoin_SpendUTXOEvent) +- [Struct `ReceiveUTXOEvent`](#0x4_bitcoin_ReceiveUTXOEvent) - [Constants](#@Constants_0) - [Function `genesis_init`](#0x4_bitcoin_genesis_init) - [Function `get_tx`](#0x4_bitcoin_get_tx) @@ -21,7 +22,8 @@ - [Function `get_latest_block`](#0x4_bitcoin_get_latest_block) - [Function `get_bitcoin_time`](#0x4_bitcoin_get_bitcoin_time) - [Function `contains_header`](#0x4_bitcoin_contains_header) -- [Function `unpack_transfer_utxo_event`](#0x4_bitcoin_unpack_transfer_utxo_event) +- [Function `unpack_spend_utxo_event`](#0x4_bitcoin_unpack_spend_utxo_event) +- [Function `unpack_receive_utxo_event`](#0x4_bitcoin_unpack_receive_utxo_event)
use 0x1::option;
@@ -81,13 +83,24 @@
-
+
-## Struct `TransferUTXOEvent`
+## Struct `SpendUTXOEvent`
-struct TransferUTXOEvent has copy, drop, store
+struct SpendUTXOEvent has copy, drop, store
+
+
+
+
+
+
+## Struct `ReceiveUTXOEvent`
+
+
+
+struct ReceiveUTXOEvent has copy, drop, store
@@ -280,11 +293,22 @@ Get the bitcoin time in seconds
-
+
+
+## Function `unpack_spend_utxo_event`
+
+
+
+public fun unpack_spend_utxo_event(event: bitcoin::SpendUTXOEvent): (address, address, option::Option<address>, u64)
+
+
+
+
+
-## Function `unpack_transfer_utxo_event`
+## Function `unpack_receive_utxo_event`
-public fun unpack_transfer_utxo_event(event: bitcoin::TransferUTXOEvent): (address, option::Option<address>, address, u64)
+public fun unpack_receive_utxo_event(event: bitcoin::ReceiveUTXOEvent): (address, option::Option<address>, address, u64)
diff --git a/frameworks/bitcoin-move/sources/bitcoin.move b/frameworks/bitcoin-move/sources/bitcoin.move
index 8b8b7e9bda..5dfbcd921b 100644
--- a/frameworks/bitcoin-move/sources/bitcoin.move
+++ b/frameworks/bitcoin-move/sources/bitcoin.move
@@ -67,7 +67,14 @@ module bitcoin_move::bitcoin{
}
- struct TransferUTXOEvent has drop, store, copy {
+ struct SpendUTXOEvent has drop, store, copy {
+ txid: address,
+ sender: address,
+ receiver: Option,
+ value: u64
+ }
+
+ struct ReceiveUTXOEvent has drop, store, copy {
txid: address,
sender: Option,
receiver: address,
@@ -237,7 +244,7 @@ module bitcoin_move::bitcoin{
let owner_address = types::txout_object_address(txout);
utxo::transfer(utxo_obj, owner_address);
if (owner_address != @bitcoin_move){
- event_queue::emit(to_string(&owner_address), TransferUTXOEvent{
+ event_queue::emit(to_string(&owner_address), ReceiveUTXOEvent {
txid,
sender,
receiver: owner_address,
@@ -246,10 +253,15 @@ module bitcoin_move::bitcoin{
};
if (option::is_some(&sender)){
let sender_address = option::extract(&mut sender);
- event_queue::emit(to_string(&sender_address), TransferUTXOEvent{
+ let receiver_address = if (owner_address != @bitcoin_move) {
+ option::some(owner_address)
+ }else {
+ option::none()
+ };
+ event_queue::emit(to_string(&sender_address), SpendUTXOEvent {
txid,
- sender,
- receiver: owner_address,
+ sender: sender_address,
+ receiver: receiver_address,
value
});
};
@@ -420,8 +432,13 @@ module bitcoin_move::bitcoin{
execute_l1_tx(block_hash, types::tx_id(&coinbase_tx));
}
- public fun unpack_transfer_utxo_event(event: TransferUTXOEvent): (address, Option, address, u64) {
- let TransferUTXOEvent { txid, sender, receiver, value } = event;
+ public fun unpack_spend_utxo_event(event: SpendUTXOEvent): (address, address, Option, u64) {
+ let SpendUTXOEvent { txid, sender, receiver, value } = event;
+ (txid, sender, receiver, value)
+ }
+
+ public fun unpack_receive_utxo_event(event: ReceiveUTXOEvent): (address, Option, address, u64) {
+ let ReceiveUTXOEvent { txid, sender, receiver, value } = event;
(txid, sender, receiver, value)
}
diff --git a/frameworks/framework-release/released/8/stdlib b/frameworks/framework-release/released/8/stdlib
index cf81b625ba..2ff9c31c77 100644
Binary files a/frameworks/framework-release/released/8/stdlib and b/frameworks/framework-release/released/8/stdlib differ
diff --git a/frameworks/moveos-stdlib/doc/README.md b/frameworks/moveos-stdlib/doc/README.md
index 2d8ecc937a..d75936a65e 100644
--- a/frameworks/moveos-stdlib/doc/README.md
+++ b/frameworks/moveos-stdlib/doc/README.md
@@ -25,6 +25,7 @@ This is the reference documentation of the MoveOS standard library.
- [`0x2::compare`](compare.md#0x2_compare)
- [`0x2::copyable_any`](copyable_any.md#0x2_copyable_any)
- [`0x2::core_addresses`](core_addresses.md#0x2_core_addresses)
+- [`0x2::decimal_value`](decimal_value.md#0x2_decimal_value)
- [`0x2::display`](display.md#0x2_display)
- [`0x2::event`](event.md#0x2_event)
- [`0x2::event_queue`](event_queue.md#0x2_event_queue)
diff --git a/frameworks/moveos-stdlib/doc/address.md b/frameworks/moveos-stdlib/doc/address.md
index 98624113c6..5b5296a47b 100644
--- a/frameworks/moveos-stdlib/doc/address.md
+++ b/frameworks/moveos-stdlib/doc/address.md
@@ -68,7 +68,7 @@ The length of an address, in bytes
-const MAX: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+const MAX: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
@@ -207,7 +207,7 @@ Length of a Rooch address in bytes
Largest possible address
-public fun max(): u256
+public fun max(): u256
diff --git a/frameworks/moveos-stdlib/doc/bcs.md b/frameworks/moveos-stdlib/doc/bcs.md
index 5a4848381a..12d47b7147 100644
--- a/frameworks/moveos-stdlib/doc/bcs.md
+++ b/frameworks/moveos-stdlib/doc/bcs.md
@@ -311,10 +311,10 @@ Read u128
value from bcs-serialized bytes.
## Function `peel_u256`
-Read u256
value from bcs-serialized bytes.
+Read u256
value from bcs-serialized bytes.
-public fun peel_u256(bcs: &mut bcs::BCS): u256
+public fun peel_u256(bcs: &mut bcs::BCS): u256
@@ -435,10 +435,10 @@ Peel a vector of u128
from serialized bytes.
## Function `peel_vec_u256`
-Peel a vector of u256
from serialized bytes.
+Peel a vector of u256
from serialized bytes.
-public fun peel_vec_u256(bcs: &mut bcs::BCS): vector<u256>
+public fun peel_vec_u256(bcs: &mut bcs::BCS): vector<u256>
@@ -531,10 +531,10 @@ Peel Option<u128>
from serialized bytes.
## Function `peel_option_u256`
-Peel Option<u256>
from serialized bytes.
+Peel Option<u256>
from serialized bytes.
-public fun peel_option_u256(bcs: &mut bcs::BCS): option::Option<u256>
+public fun peel_option_u256(bcs: &mut bcs::BCS): option::Option<u256>
diff --git a/frameworks/moveos-stdlib/doc/compare.md b/frameworks/moveos-stdlib/doc/compare.md
index 79910ea4fd..132065f440 100644
--- a/frameworks/moveos-stdlib/doc/compare.md
+++ b/frameworks/moveos-stdlib/doc/compare.md
@@ -17,7 +17,9 @@ Utilities for comparing Move values
use 0x1::compare;
use 0x1::type_name;
+use 0x1::u256;
use 0x2::bcs;
+use 0x2::decimal_value;
diff --git a/frameworks/moveos-stdlib/doc/decimal_value.md b/frameworks/moveos-stdlib/doc/decimal_value.md
new file mode 100644
index 0000000000..8056500c29
--- /dev/null
+++ b/frameworks/moveos-stdlib/doc/decimal_value.md
@@ -0,0 +1,58 @@
+
+
+
+# Module `0x2::decimal_value`
+
+
+
+- [Struct `DecimalValue`](#0x2_decimal_value_DecimalValue)
+- [Function `new`](#0x2_decimal_value_new)
+- [Function `value`](#0x2_decimal_value_value)
+- [Function `decimal`](#0x2_decimal_value_decimal)
+
+
+
+
+
+
+
+
+## Struct `DecimalValue`
+
+
+
+struct DecimalValue has copy, drop, store
+
+
+
+
+
+
+## Function `new`
+
+
+
+public fun new(value: u64, decimal: u8): decimal_value::DecimalValue
+
+
+
+
+
+
+## Function `value`
+
+
+
+public fun value(self: &decimal_value::DecimalValue): u64
+
+
+
+
+
+
+## Function `decimal`
+
+
+
+public fun decimal(self: &decimal_value::DecimalValue): u8
+
diff --git a/frameworks/moveos-stdlib/doc/move_module.md b/frameworks/moveos-stdlib/doc/move_module.md
index fbdebccdc8..0bc811a2c7 100644
--- a/frameworks/moveos-stdlib/doc/move_module.md
+++ b/frameworks/moveos-stdlib/doc/move_module.md
@@ -263,7 +263,7 @@ Replace given u64 constant to the new ones
Replace given u256 constant to the new ones
-public fun replace_constant_u256(modules: vector<move_module::MoveModule>, old_u256s: vector<u256>, new_u256s: vector<u256>): vector<move_module::MoveModule>
+public fun replace_constant_u256(modules: vector<move_module::MoveModule>, old_u256s: vector<u256>, new_u256s: vector<u256>): vector<move_module::MoveModule>
@@ -393,5 +393,5 @@ Native function to replace constant u256 in module binary where the length of
old_u256s
must equal to that of new_u256s
.
-public(friend) fun replace_u256_constant(bytes: vector<vector<u8>>, old_u256s: vector<u256>, new_u256s: vector<u256>): vector<vector<u8>>
+public(friend) fun replace_u256_constant(bytes: vector<vector<u8>>, old_u256s: vector<u256>, new_u256s: vector<u256>): vector<vector<u8>>
diff --git a/frameworks/moveos-stdlib/doc/string_utils.md b/frameworks/moveos-stdlib/doc/string_utils.md
index 1af1bd76f0..361d568361 100644
--- a/frameworks/moveos-stdlib/doc/string_utils.md
+++ b/frameworks/moveos-stdlib/doc/string_utils.md
@@ -116,7 +116,7 @@
-public fun parse_u256_option(s: &string::String): option::Option<u256>
+public fun parse_u256_option(s: &string::String): option::Option<u256>
@@ -127,7 +127,7 @@
-public fun parse_u256(s: &string::String): u256
+public fun parse_u256(s: &string::String): u256
@@ -138,7 +138,7 @@
-public fun parse_decimal_option(s: &string::String, decimal: u64): option::Option<u256>
+public fun parse_decimal_option(s: &string::String, decimal: u64): option::Option<u256>
@@ -149,7 +149,7 @@
-public fun parse_decimal(s: &string::String, decimal: u64): u256
+public fun parse_decimal(s: &string::String, decimal: u64): u256
@@ -182,7 +182,7 @@
-public fun to_string_u256(n: u256): string::String
+public fun to_string_u256(n: u256): string::String
diff --git a/frameworks/moveos-stdlib/sources/bcs.move b/frameworks/moveos-stdlib/sources/bcs.move
index bf17bf4c6c..a2a6a991aa 100644
--- a/frameworks/moveos-stdlib/sources/bcs.move
+++ b/frameworks/moveos-stdlib/sources/bcs.move
@@ -10,6 +10,8 @@ module moveos_std::bcs{
use std::option::{Self, Option};
use std::vector;
+ #[test_only]
+ use std::vector::{is_empty, pop_back};
friend moveos_std::any;
friend moveos_std::copyable_any;
@@ -74,12 +76,11 @@ module moveos_std::bcs{
/// Read `address` value from the bcs-serialized bytes.
public fun peel_address(bcs: &mut BCS): address {
- let bytes = bcs.bytes;
- assert!(vector::length(&bytes) >= 32, ErrorInvalidLength);
+ assert!(vector::length(&bcs.bytes) >= 32, ErrorInvalidLength);
let i = 0;
let addr_bytes = vector::empty();
while (i < 32) {
- let byte = vector::pop_back(&mut bytes);
+ let byte = vector::pop_back(&mut bcs.bytes);
vector::push_back(&mut addr_bytes, byte);
i = i + 1;
};
@@ -100,20 +101,18 @@ module moveos_std::bcs{
/// Read `u8` value from bcs-serialized bytes.
public fun peel_u8(bcs: &mut BCS): u8 {
- let bytes = bcs.bytes;
- assert!(vector::length(&bytes) >= 1, ErrorOutOfRange);
- vector::pop_back(&mut bytes)
+ assert!(vector::length(&bcs.bytes) >= 1, ErrorOutOfRange);
+ vector::pop_back(&mut bcs.bytes)
}
/// Read `u16` value from bcs-serialized bytes.
public fun peel_u16(bcs: &mut BCS): u16 {
- let bytes = bcs.bytes;
- assert!(vector::length(&bytes) >= 2, ErrorOutOfRange);
+ assert!(vector::length(&bcs.bytes) >= 2, ErrorOutOfRange);
let value = 0;
let i = 0;
let bits = 16u8;
while (i < bits) {
- let byte = (vector::pop_back(&mut bytes) as u16);
+ let byte = (vector::pop_back(&mut bcs.bytes) as u16);
value = value + (byte << (i as u8));
i = i + 8;
};
@@ -123,13 +122,12 @@ module moveos_std::bcs{
/// Read `u32` value from bcs-serialized bytes.
public fun peel_u32(bcs: &mut BCS): u32 {
- let bytes = bcs.bytes;
- assert!(vector::length(&bytes) >= 4, ErrorOutOfRange);
+ assert!(vector::length(&bcs.bytes) >= 4, ErrorOutOfRange);
let value = 0;
let i = 0;
let bits = 32u8;
while (i < bits) {
- let byte = (vector::pop_back(&mut bytes) as u32);
+ let byte = (vector::pop_back(&mut bcs.bytes) as u32);
value = value + (byte << (i as u8));
i = i + 8;
};
@@ -139,13 +137,12 @@ module moveos_std::bcs{
/// Read `u64` value from bcs-serialized bytes.
public fun peel_u64(bcs: &mut BCS): u64 {
- let bytes = bcs.bytes;
- assert!(vector::length(&bytes) >= 8, ErrorOutOfRange);
+ assert!(vector::length(&bcs.bytes) >= 8, ErrorOutOfRange);
let value = 0;
let i = 0;
let bits = 64u8;
while (i < bits) {
- let byte = (vector::pop_back(&mut bytes) as u64);
+ let byte = (vector::pop_back(&mut bcs.bytes) as u64);
value = value + (byte << (i as u8));
i = i + 8;
};
@@ -155,13 +152,12 @@ module moveos_std::bcs{
/// Read `u128` value from bcs-serialized bytes.
public fun peel_u128(bcs: &mut BCS): u128 {
- let bytes = bcs.bytes;
- assert!(vector::length(&bytes) >= 16, ErrorOutOfRange);
+ assert!(vector::length(&bcs.bytes) >= 16, ErrorOutOfRange);
let value = 0;
let i = 0;
let bits = 128u8;
while (i < bits) {
- let byte = (vector::pop_back(&mut bytes) as u128);
+ let byte = (vector::pop_back(&mut bcs.bytes) as u128);
value = value + (byte << (i as u8));
i = i + 8;
};
@@ -171,13 +167,12 @@ module moveos_std::bcs{
/// Read `u256` value from bcs-serialized bytes.
public fun peel_u256(bcs: &mut BCS): u256 {
- let bytes = bcs.bytes;
- assert!(vector::length(&bytes) >= 32, ErrorOutOfRange);
+ assert!(vector::length(&bcs.bytes) >= 32, ErrorOutOfRange);
let value = 0;
let i = 0;
let bits = 256u16;
while (i < bits) {
- let byte = (vector::pop_back(&mut bytes) as u256);
+ let byte = (vector::pop_back(&mut bcs.bytes) as u256);
value = value + (byte << (i as u8));
i = i + 8;
};
@@ -193,13 +188,12 @@ module moveos_std::bcs{
/// In BCS `vector` length is implemented with ULEB128;
/// See more here: https://en.wikipedia.org/wiki/LEB128
public fun peel_vec_length(bcs: &mut BCS): u64 {
- let bytes = bcs.bytes;
let total = 0u64;
let shift = 0;
let len = 0;
loop {
assert!(len <= 4, ErrorLengthOutOfRange);
- let byte = (vector::pop_back(&mut bytes) as u64);
+ let byte = (vector::pop_back(&mut bcs.bytes) as u64);
len = len + 1;
total = total | ((byte & 0x7f) << shift);
if ((byte & 0x80) == 0) {
@@ -574,205 +568,78 @@ module moveos_std::bcs{
}
#[test]
- fun test_peel_vec_address_success() {
- let bytes = x"7fe695faf7047ccfbc85f7dccb6c405d4e9b7b44788e71a71c3891a06ce0ca12";
- let bcs = new(bytes);
- let vec_address = peel_vec_address(&mut bcs);
- let expected_vec_address = vector::empty();
- let expected_address = @0x7fe695faf7047ccfbc85f7dccb6c405d4e9b7b44788e71a71c3891a06ce0ca12;
- let i = 0;
- while (i < vector::length(&vec_address)) {
- vector::push_back(&mut expected_vec_address, expected_address);
- i = i + 1;
+ fun test_vec() {
+ let bool_cases = vector[vector[], vector[true], vector[false, true, false]];
+ let excepet_bool_cases = bool_cases;
+ while (!is_empty(&excepet_bool_cases)) {
+ let case = pop_back(&mut excepet_bool_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_bool(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
};
- assert!(vec_address == expected_vec_address, ErrorLengthOutOfRange);
- }
- #[test]
- fun test_peel_vec_bool_success() {
- let bytes = x"01";
- let bcs = new(bytes);
- let vec_bool = peel_vec_bool(&mut bcs);
- let expected_vec_bool = vector::empty();
- let expected_bool = true;
- vector::push_back(&mut expected_vec_bool, expected_bool);
- assert!(vec_bool == expected_vec_bool, ErrorLengthOutOfRange);
- }
-
- #[test]
- fun test_peel_vec_u8_success() {
- let bytes = x"11";
- let bcs = new(bytes);
- let u8 = peel_vec_u8(&mut bcs);
- let expected_vec_u8 = x"1111111111111111111111111111111111";
- assert!(u8 == expected_vec_u8, ErrorLengthOutOfRange);
- }
-
- #[test]
- fun test_peel_vec_vec_u8_success() {
- let bytes = x"11";
- let bcs = new(bytes);
- let vec_vec_u8 = peel_vec_vec_u8(&mut bcs);
- let expected_vec_vec_u8 = vector::empty>();
- let expected_vec_u8 = x"1111111111111111111111111111111111";
- let i = 0;
- while (i < vector::length(&vec_vec_u8)) {
- vector::push_back(&mut expected_vec_vec_u8, expected_vec_u8);
- i = i + 1;
+ let u8_cases = vector[vector[], vector[1], vector[0, 2, 0xFF]];
+ let excepet_u8_cases = u8_cases;
+ while (!is_empty(&excepet_u8_cases)) {
+ let case = pop_back(&mut excepet_u8_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_u8(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
};
- assert!(vec_vec_u8 == expected_vec_vec_u8, ErrorLengthOutOfRange);
- }
- #[test]
- fun test_peel_vec_u16_success() {
- let bytes = x"1111";
- let bcs = new(bytes);
- let vec_u16 = peel_vec_u16(&mut bcs);
- let expected_vec_u16 = vector::empty();
- let expected_u16 = 4369u16;
- let i = 0;
- while (i < vector::length(&vec_u16)) {
- vector::push_back(&mut expected_vec_u16, expected_u16);
- i = i + 1;
+ let u16_cases = vector[vector[], vector[1], vector[0, 2, 0xFFFF]];
+ let excepet_u16_cases = u16_cases;
+ while (!is_empty(&excepet_u16_cases)) {
+ let case = pop_back(&mut excepet_u16_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_u16(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
};
- assert!(vec_u16 == expected_vec_u16, ErrorLengthOutOfRange);
- }
- #[test]
- fun test_peel_vec_u32_success() {
- let bytes = x"11111111";
- let bcs = new(bytes);
- let vec_u32 = peel_vec_u32(&mut bcs);
- let expected_vec_u32 = vector::empty();
- let expected_u32 = 286331153u32;
- let i = 0;
- while (i < vector::length(&vec_u32)) {
- vector::push_back(&mut expected_vec_u32, expected_u32);
- i = i + 1;
+ let u32_cases = vector[vector[], vector[1], vector[0, 2, 0xFFFF_FFFF]];
+ let excepet_u32_cases = u32_cases;
+ while (!is_empty(&excepet_u32_cases)) {
+ let case = pop_back(&mut excepet_u32_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_u32(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
};
- assert!(vec_u32 == expected_vec_u32, ErrorLengthOutOfRange);
- }
- #[test]
- fun test_peel_vec_u64_success() {
- let bytes = x"1111111111111111";
- let bcs = new(bytes);
- let vec_u64 = peel_vec_u64(&mut bcs);
- let expected_vec_u64 = vector::empty();
- let expected_u64 = 1229782938247303441u64;
- let i = 0;
- while (i < vector::length(&vec_u64)) {
- vector::push_back(&mut expected_vec_u64, expected_u64);
- i = i + 1;
+ let u64_cases = vector[vector[], vector[1], vector[0, 2, 0xFFFF_FFFF_FFFF_FFFF]];
+ let excepet_u64_cases = u64_cases;
+ while (!is_empty(&excepet_u64_cases)) {
+ let case = pop_back(&mut excepet_u64_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_u64(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
};
- assert!(vec_u64 == expected_vec_u64, ErrorLengthOutOfRange);
- }
- #[test]
- fun test_peel_vec_u128_success() {
- let bytes = x"11111111111111111111111111111111";
- let bcs = new(bytes);
- let vec_u128 = peel_vec_u128(&mut bcs);
- let expected_vec_u128 = vector::empty();
- let expected_u128 = 22685491128062564230891640495451214097u128;
- let i = 0;
- while (i < vector::length(&vec_u128)) {
- vector::push_back(&mut expected_vec_u128, expected_u128);
- i = i + 1;
+ let u128_cases = vector[vector[], vector[1], vector[0, 2, 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF]];
+ let excepet_u128_cases = u128_cases;
+ while (!is_empty(&excepet_u128_cases)) {
+ let case = pop_back(&mut excepet_u128_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_u128(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
};
- assert!(vec_u128 == expected_vec_u128, ErrorLengthOutOfRange);
- }
- #[test]
- fun test_peel_vec_u256_success() {
- let bytes = x"1111111111111111111111111111111111111111111111111111111111111111";
- let bcs = new(bytes);
- let vec_u256 = peel_vec_u256(&mut bcs);
- let expected_vec_u256 = vector::empty();
- let expected_u256 = 7719472615821079694904732333912527190217998977709370935963838933860875309329u256;
- let i = 0;
- while (i < vector::length(&vec_u256)) {
- vector::push_back(&mut expected_vec_u256, expected_u256);
- i = i + 1;
+ let u256_cases = vector[vector[], vector[1], vector[0, 2, 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF]];
+ let excepet_u256_cases = u256_cases;
+ while (!is_empty(&excepet_u256_cases)) {
+ let case = pop_back(&mut excepet_u256_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_u256(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
};
- assert!(vec_u256 == expected_vec_u256, ErrorLengthOutOfRange);
- }
-
- #[test]
- fun test_peel_option_address_success() {
- let bytes = x"017fe695faf7047ccfbc85f7dccb6c405d4e9b7b44788e71a71c3891a06ce0ca12";
- let bcs = new(bytes);
- let option_address = peel_option_address(&mut bcs);
- let expected_option_addr = option::some(@0x17fe695faf7047ccfbc85f7dccb6c405d4e9b7b44788e71a71c3891a06ce0ca);
- assert!(option_address == expected_option_addr, ErrorInvalidLength);
- }
-
- #[test]
- fun test_peel_option_bool_success() {
- let bytes = x"01";
- let bcs = new(bytes);
- let option_bool = peel_option_bool(&mut bcs);
- let expected_option_bool = option::some(true);
- assert!(option_bool == expected_option_bool, ErrorInvalidBool);
- }
-
- #[test]
- fun test_peel_option_u8_success() {
- let bytes = x"0101";
- let bcs = new(bytes);
- let option_u8 = peel_option_u8(&mut bcs);
- std::debug::print(&option_u8);
- let expected_option_u8 = option::some(1);
- assert!(option_u8 == expected_option_u8, ErrorOutOfRange);
- }
- #[test]
- fun test_peel_option_u16_success() {
- let bytes = x"010011";
- let bcs = new(bytes);
- let option_u16 = peel_option_u16(&mut bcs);
- std::debug::print(&option_u16);
- let expected_option_u16 = option::some(1);
- assert!(option_u16 == expected_option_u16, ErrorOutOfRange);
- }
-
- #[test]
- fun test_peel_option_u32_success() {
- let bytes = x"0100001111";
- let bcs = new(bytes);
- let option_u32 = peel_option_u32(&mut bcs);
- std::debug::print(&option_u32);
- let expected_option_u32 = option::some(285212673);
- assert!(option_u32 == expected_option_u32, ErrorOutOfRange);
- }
-
- #[test]
- fun test_peel_option_u64_success() {
- let bytes = x"010000000011111111";
- let bcs = new(bytes);
- let option_u64 = peel_option_u64(&mut bcs);
- std::debug::print(&option_u64);
- let expected_option_u64 = option::some(1229782864946528257);
- assert!(option_u64 == expected_option_u64, ErrorOutOfRange);
- }
-
- #[test]
- fun test_peel_option_u128_success() {
- let bytes = x"0100000000111111110000000011111111";
- let bcs = new(bytes);
- let option_u128 = peel_option_u128(&mut bcs);
- std::debug::print(&option_u128);
- let expected_option_u128 = option::some(22685489775901924302271377683643367425);
- assert!(option_u128 == expected_option_u128, ErrorOutOfRange);
- }
+ let address_cases = vector[vector[], vector[@0x0], vector[@0x1, @0x2, @0x3]];
+ let excepet_address_cases = address_cases;
+ while (!is_empty(&excepet_address_cases)) {
+ let case = pop_back(&mut excepet_address_cases);
+ let bytes = new(to_bytes(&case));
+ assert!(peel_vec_address(&mut bytes) == case, 0);
+ assert!(is_empty(&into_remainder_bytes(bytes)), 1);
+ };
- #[test]
- fun test_peel_option_u256_success() {
- let bytes = x"010000000011111111000000001111111100000000111111110000000011111111";
- let bcs = new(bytes);
- let option_u256 = peel_option_u256(&mut bcs);
- std::debug::print(&option_u256);
- let expected_option_u256 = option::some(7719472155704656682663016097251860136573850893801914284240011010441236971521);
- assert!(option_u256 == expected_option_u256, ErrorOutOfRange);
}
}
diff --git a/frameworks/moveos-stdlib/sources/compare.move b/frameworks/moveos-stdlib/sources/compare.move
index e651574900..0de19f612e 100644
--- a/frameworks/moveos-stdlib/sources/compare.move
+++ b/frameworks/moveos-stdlib/sources/compare.move
@@ -2,6 +2,8 @@
module moveos_std::compare {
use std::vector;
use std::type_name;
+ use std::u256;
+ use moveos_std::decimal_value::DecimalValue;
use moveos_std::bcs;
@@ -95,7 +97,24 @@ module moveos_std::compare {
} else {
return LESS_THAN
}
- }else {
+ } else if (t == type_name::get()) {
+ let a_value = bcs::peel_u64(&mut a);
+ let a_decimal = bcs::peel_u8(&mut a);
+ let b_value = bcs::peel_u64(&mut b);
+ let b_decimal = bcs::peel_u8(&mut b);
+ // Normalise the decimal values
+ let a = (a_value as u256) * u256::pow(10, b_decimal);
+ let b = (b_value as u256) * u256::pow(10, a_decimal);
+
+ if (a > b) {
+ return GREATER_THAN
+ } else if (a == b) {
+ return EQUAL
+ } else {
+ return LESS_THAN
+ }
+ }
+ else {
compare_vector_u8(&bcs::into_remainder_bytes(a), &bcs::into_remainder_bytes(b))
}
}
diff --git a/frameworks/moveos-stdlib/sources/decimal_value.move b/frameworks/moveos-stdlib/sources/decimal_value.move
new file mode 100644
index 0000000000..975ef3ad43
--- /dev/null
+++ b/frameworks/moveos-stdlib/sources/decimal_value.move
@@ -0,0 +1,21 @@
+// Copyright (c) RoochNetwork
+// SPDX-License-Identifier: Apache-2.0
+
+module moveos_std::decimal_value {
+ struct DecimalValue has store, drop, copy {
+ value: u64,
+ decimal: u8,
+ }
+
+ public fun new(value: u64, decimal: u8): DecimalValue {
+ DecimalValue { value, decimal }
+ }
+
+ public fun value(self: &DecimalValue): u64 {
+ self.value
+ }
+
+ public fun decimal(self: &DecimalValue): u8 {
+ self.decimal
+ }
+}
\ No newline at end of file
diff --git a/frameworks/rooch-framework/doc/README.md b/frameworks/rooch-framework/doc/README.md
index d5bca85a80..d025e71c48 100644
--- a/frameworks/rooch-framework/doc/README.md
+++ b/frameworks/rooch-framework/doc/README.md
@@ -34,6 +34,9 @@ This is the reference documentation of the Rooch Framework.
- [`0x3::genesis`](genesis.md#0x3_genesis)
- [`0x3::multichain_address`](multichain_address.md#0x3_multichain_address)
- [`0x3::onchain_config`](onchain_config.md#0x3_onchain_config)
+- [`0x3::oracle`](oracle.md#0x3_oracle)
+- [`0x3::oracle_data`](oracle_data.md#0x3_oracle_data)
+- [`0x3::oracle_meta`](oracle_meta.md#0x3_oracle_meta)
- [`0x3::session_key`](session_key.md#0x3_session_key)
- [`0x3::session_validator`](session_validator.md#0x3_session_validator)
- [`0x3::simple_rng`](simple_rng.md#0x3_simple_rng)
diff --git a/frameworks/rooch-framework/doc/account_coin_store.md b/frameworks/rooch-framework/doc/account_coin_store.md
index 3b887eeb88..696aa909fd 100644
--- a/frameworks/rooch-framework/doc/account_coin_store.md
+++ b/frameworks/rooch-framework/doc/account_coin_store.md
@@ -97,7 +97,7 @@ Account hasn't accept CoinType
Returns the balance of addr
for provided CoinType
.
-public fun balance<CoinType: key>(addr: address): u256
+public fun balance<CoinType: key>(addr: address): u256
@@ -173,7 +173,7 @@ Withdraw specified amount
of coin CoinType
from the si
This public entry function requires the CoinType
to have key
and store
abilities.
-public fun withdraw<CoinType: store, key>(account: &signer, amount: u256): coin::Coin<CoinType>
+public fun withdraw<CoinType: store, key>(account: &signer, amount: u256): coin::Coin<CoinType>
@@ -199,7 +199,7 @@ Transfer amount
of coins CoinType
from fromCoinType
must have key
and store
abilities.
-public fun transfer<CoinType: store, key>(from: &signer, to: address, amount: u256)
+public fun transfer<CoinType: store, key>(from: &signer, to: address, amount: u256)
@@ -235,7 +235,7 @@ This function is only called by the CoinType
module, for the develo
#[private_generics(#[CoinType])]
-public fun withdraw_extend<CoinType: key>(addr: address, amount: u256): coin::Coin<CoinType>
+public fun withdraw_extend<CoinType: key>(addr: address, amount: u256): coin::Coin<CoinType>
@@ -263,7 +263,7 @@ This function is only called by the CoinType
module, for the develo
#[private_generics(#[CoinType])]
-public fun transfer_extend<CoinType: key>(from: address, to: address, amount: u256)
+public fun transfer_extend<CoinType: key>(from: address, to: address, amount: u256)
diff --git a/frameworks/rooch-framework/doc/coin.md b/frameworks/rooch-framework/doc/coin.md
index 46572f19f3..487c83ff7c 100644
--- a/frameworks/rooch-framework/doc/coin.md
+++ b/frameworks/rooch-framework/doc/coin.md
@@ -130,7 +130,7 @@ Maximum possible coin supply.
-const MAX_U256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+const MAX_U256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
@@ -337,7 +337,7 @@ be displayed to a user as 5.05
(505 / 10 ** 2
).
Returns the amount of coin in existence.
-public fun supply<CoinType: key>(coin_info: &coin::CoinInfo<CoinType>): u256
+public fun supply<CoinType: key>(coin_info: &coin::CoinInfo<CoinType>): u256
@@ -386,7 +386,7 @@ so it is impossible to "burn" any non-zero amount of coin
, where the original coin is modified in place.
-public fun extract<CoinType: key>(coin: &mut coin::Coin<CoinType>, amount: u256): coin::Coin<CoinType>
+public fun extract<CoinType: key>(coin: &mut coin::Coin<CoinType>, amount: u256): coin::Coin<CoinType>
@@ -423,7 +423,7 @@ to the sum of the two coins (dst_coin
and source_coin
)
Returns the value
passed in coin
.
-public fun value<CoinType: key>(coin: &coin::Coin<CoinType>): u256
+public fun value<CoinType: key>(coin: &coin::Coin<CoinType>): u256
@@ -487,7 +487,7 @@ This function is protected by private_generics
, so it can only be c
Public coin can mint by anyone with the mutable Object>
-public fun mint<CoinType: store, key>(coin_info: &mut object::Object<coin::CoinInfo<CoinType>>, amount: u256): coin::Coin<CoinType>
+public fun mint<CoinType: store, key>(coin_info: &mut object::Object<coin::CoinInfo<CoinType>>, amount: u256): coin::Coin<CoinType>
@@ -500,7 +500,7 @@ Mint new Coin
, this function is
#[private_generics(#[CoinType])]
-public fun mint_extend<CoinType: key>(coin_info: &mut object::Object<coin::CoinInfo<CoinType>>, amount: u256): coin::Coin<CoinType>
+public fun mint_extend<CoinType: key>(coin_info: &mut object::Object<coin::CoinInfo<CoinType>>, amount: u256): coin::Coin<CoinType>
@@ -537,7 +537,7 @@ This function is only called by the CoinType
module, for the develo
-public(friend) fun unpack<CoinType: key>(coin: coin::Coin<CoinType>): u256
+public(friend) fun unpack<CoinType: key>(coin: coin::Coin<CoinType>): u256
@@ -548,5 +548,5 @@ This function is only called by the CoinType
module, for the develo
-public(friend) fun pack<CoinType: key>(value: u256): coin::Coin<CoinType>
+public(friend) fun pack<CoinType: key>(value: u256): coin::Coin<CoinType>
diff --git a/frameworks/rooch-framework/doc/coin_store.md b/frameworks/rooch-framework/doc/coin_store.md
index 568c652cb5..8631b742dc 100644
--- a/frameworks/rooch-framework/doc/coin_store.md
+++ b/frameworks/rooch-framework/doc/coin_store.md
@@ -225,7 +225,7 @@ Remove the CoinStore Object, return the Coin in balance
-public fun balance<CoinType: key>(coin_store_obj: &object::Object<coin_store::CoinStore<CoinType>>): u256
+public fun balance<CoinType: key>(coin_store_obj: &object::Object<coin_store::CoinStore<CoinType>>): u256
@@ -249,7 +249,7 @@ Withdraw amount
Coin from the balance of the passed-in CoinType
must has key
and store
ability
-public fun withdraw<CoinType: store, key>(coin_store_obj: &mut object::Object<coin_store::CoinStore<CoinType>>, amount: u256): coin::Coin<CoinType>
+public fun withdraw<CoinType: store, key>(coin_store_obj: &mut object::Object<coin_store::CoinStore<CoinType>>, amount: u256): coin::Coin<CoinType>
@@ -263,7 +263,7 @@ This function is for the CoinType
module to extend
#[private_generics(#[CoinType])]
-public fun withdraw_extend<CoinType: key>(coin_store_obj: &mut object::Object<coin_store::CoinStore<CoinType>>, amount: u256): coin::Coin<CoinType>
+public fun withdraw_extend<CoinType: key>(coin_store_obj: &mut object::Object<coin_store::CoinStore<CoinType>>, amount: u256): coin::Coin<CoinType>
@@ -374,7 +374,7 @@ Only the CoinType
module can freeze or unfreeze a CoinStore by the
-public(friend) fun withdraw_internal<CoinType: key>(coin_store_obj: &mut object::Object<coin_store::CoinStore<CoinType>>, amount: u256): coin::Coin<CoinType>
+public(friend) fun withdraw_internal<CoinType: key>(coin_store_obj: &mut object::Object<coin_store::CoinStore<CoinType>>, amount: u256): coin::Coin<CoinType>
diff --git a/frameworks/rooch-framework/doc/gas_coin.md b/frameworks/rooch-framework/doc/gas_coin.md
index df2642ea89..7abdcafcaf 100644
--- a/frameworks/rooch-framework/doc/gas_coin.md
+++ b/frameworks/rooch-framework/doc/gas_coin.md
@@ -70,7 +70,7 @@ This module defines Rooch Gas Coin.
-public fun balance(addr: address): u256
+public fun balance(addr: address): u256
@@ -93,7 +93,7 @@ This module defines Rooch Gas Coin.
deduct gas coin from the given account.
-public(friend) fun deduct_gas(addr: address, amount: u256): coin::Coin<gas_coin::GasCoin>
+public(friend) fun deduct_gas(addr: address, amount: u256): coin::Coin<gas_coin::GasCoin>
@@ -105,7 +105,7 @@ deduct gas coin from the given account.
Mint gas coin to the given account.
-public(friend) fun faucet(addr: address, amount: u256)
+public(friend) fun faucet(addr: address, amount: u256)
@@ -117,7 +117,7 @@ Mint gas coin to the given account.
Entry point for the faucet, anyone can get Gas via this function on local/dev net, otherwise only sequencer account can call this function.
-public entry fun faucet_entry(account: &signer, amount: u256)
+public entry fun faucet_entry(account: &signer, amount: u256)
diff --git a/frameworks/rooch-framework/doc/oracle.md b/frameworks/rooch-framework/doc/oracle.md
new file mode 100644
index 0000000000..8520b6debb
--- /dev/null
+++ b/frameworks/rooch-framework/doc/oracle.md
@@ -0,0 +1,138 @@
+
+
+
+# Module `0x3::oracle`
+
+
+
+- [Resource `TablePlaceholder`](#0x3_oracle_TablePlaceholder)
+- [Resource `SimpleOracle`](#0x3_oracle_SimpleOracle)
+- [Struct `StoredData`](#0x3_oracle_StoredData)
+- [Constants](#@Constants_0)
+- [Function `get_historical_data`](#0x3_oracle_get_historical_data)
+- [Function `get_latest_data`](#0x3_oracle_get_latest_data)
+- [Function `create`](#0x3_oracle_create)
+- [Function `submit_data`](#0x3_oracle_submit_data)
+- [Function `archive_data`](#0x3_oracle_archive_data)
+
+
+use 0x1::option;
+use 0x1::string;
+use 0x2::object;
+use 0x2::table;
+use 0x2::timestamp;
+use 0x2::tx_context;
+use 0x3::oracle_data;
+
+
+
+
+
+
+## Resource `TablePlaceholder`
+
+
+
+struct TablePlaceholder has key
+
+
+
+
+
+
+## Resource `SimpleOracle`
+
+
+
+struct SimpleOracle has store, key
+
+
+
+
+
+
+## Struct `StoredData`
+
+
+
+struct StoredData<T: store> has copy, drop, store
+
+
+
+
+
+
+## Constants
+
+
+
+
+
+
+const ErrorSenderNotOracle: u64 = 0;
+
+
+
+
+
+
+
+
+const ErrorTickerNotExists: u64 = 1;
+
+
+
+
+
+
+## Function `get_historical_data`
+
+
+
+public fun get_historical_data<K: copy, drop, store, V: copy, store>(oracle_obj: &object::Object<oracle::SimpleOracle>, ticker: string::String, archival_key: K): option::Option<oracle_data::Data<V>>
+
+
+
+
+
+
+## Function `get_latest_data`
+
+
+
+public fun get_latest_data<T: copy, store>(oracle_obj: &object::Object<oracle::SimpleOracle>, ticker: string::String): option::Option<oracle_data::Data<T>>
+
+
+
+
+
+
+## Function `create`
+
+Create a new shared SimpleOracle object for publishing data.
+
+
+public entry fun create(name: string::String, url: string::String, description: string::String)
+
+
+
+
+
+
+## Function `submit_data`
+
+
+
+public fun submit_data<T: copy, drop, store>(oracle_obj: &mut object::Object<oracle::SimpleOracle>, ticker: string::String, value: T, identifier: string::String)
+
+
+
+
+
+
+## Function `archive_data`
+
+
+
+public fun archive_data<K: copy, drop, store, V: copy, drop, store>(oracle_obj: &mut object::Object<oracle::SimpleOracle>, ticker: string::String, archival_key: K)
+
diff --git a/frameworks/rooch-framework/doc/oracle_data.md b/frameworks/rooch-framework/doc/oracle_data.md
new file mode 100644
index 0000000000..9b0a9d93e7
--- /dev/null
+++ b/frameworks/rooch-framework/doc/oracle_data.md
@@ -0,0 +1,83 @@
+
+
+
+# Module `0x3::oracle_data`
+
+
+
+- [Struct `Data`](#0x3_oracle_data_Data)
+- [Struct `Metadata`](#0x3_oracle_data_Metadata)
+- [Function `new`](#0x3_oracle_data_new)
+- [Function `value`](#0x3_oracle_data_value)
+- [Function `oracle_address`](#0x3_oracle_data_oracle_address)
+- [Function `timestamp`](#0x3_oracle_data_timestamp)
+
+
+use 0x1::string;
+
+
+
+
+
+
+## Struct `Data`
+
+
+
+struct Data<T> has copy, drop
+
+
+
+
+
+
+## Struct `Metadata`
+
+
+
+struct Metadata has copy, drop
+
+
+
+
+
+
+## Function `new`
+
+
+
+public fun new<T>(value: T, ticker: string::String, sequence_number: u64, timestamp: u64, oracle: address, identifier: string::String): oracle_data::Data<T>
+
+
+
+
+
+
+## Function `value`
+
+
+
+public fun value<T>(data: &oracle_data::Data<T>): &T
+
+
+
+
+
+
+## Function `oracle_address`
+
+
+
+public fun oracle_address<T>(data: &oracle_data::Data<T>): &address
+
+
+
+
+
+
+## Function `timestamp`
+
+
+
+public fun timestamp<T>(data: &oracle_data::Data<T>): u64
+
diff --git a/frameworks/rooch-framework/doc/oracle_meta.md b/frameworks/rooch-framework/doc/oracle_meta.md
new file mode 100644
index 0000000000..827ea987cc
--- /dev/null
+++ b/frameworks/rooch-framework/doc/oracle_meta.md
@@ -0,0 +1,186 @@
+
+
+
+# Module `0x3::oracle_meta`
+
+
+
+- [Struct `MetaOracle`](#0x3_oracle_meta_MetaOracle)
+- [Struct `TrustedData`](#0x3_oracle_meta_TrustedData)
+- [Constants](#@Constants_0)
+- [Function `new`](#0x3_oracle_meta_new)
+- [Function `add_simple_oracle`](#0x3_oracle_meta_add_simple_oracle)
+- [Function `median`](#0x3_oracle_meta_median)
+- [Function `data`](#0x3_oracle_meta_data)
+- [Function `threshold`](#0x3_oracle_meta_threshold)
+- [Function `time_window_ms`](#0x3_oracle_meta_time_window_ms)
+- [Function `ticker`](#0x3_oracle_meta_ticker)
+- [Function `max_timestamp`](#0x3_oracle_meta_max_timestamp)
+- [Function `value`](#0x3_oracle_meta_value)
+- [Function `oracles`](#0x3_oracle_meta_oracles)
+
+
+use 0x1::option;
+use 0x1::string;
+use 0x1::vector;
+use 0x2::object;
+use 0x2::sort;
+use 0x3::oracle;
+use 0x3::oracle_data;
+
+
+
+
+
+
+## Struct `MetaOracle`
+
+
+
+struct MetaOracle<T>
+
+
+
+
+
+
+## Struct `TrustedData`
+
+
+
+struct TrustedData<T> has copy, drop
+
+
+
+
+
+
+## Constants
+
+
+
+
+
+
+const ErrorUnsupportedDataType: u64 = 1;
+
+
+
+
+
+
+
+
+const ErrorValidDataSizeLessThanThreshold: u64 = 0;
+
+
+
+
+
+
+## Function `new`
+
+
+
+public fun new<T: copy, drop>(threshold: u64, time_window_ms: u64, ticker: string::String): oracle_meta::MetaOracle<T>
+
+
+
+
+
+
+## Function `add_simple_oracle`
+
+
+
+public fun add_simple_oracle<T: copy, drop, store>(meta_oracle: &mut oracle_meta::MetaOracle<T>, oracle: &object::Object<oracle::SimpleOracle>)
+
+
+
+
+
+
+## Function `median`
+
+take the median value
+
+
+public fun median<T: copy, drop>(meta_oracle: oracle_meta::MetaOracle<T>): oracle_meta::TrustedData<T>
+
+
+
+
+
+
+## Function `data`
+
+
+
+public fun data<T>(meta: &oracle_meta::MetaOracle<T>): &vector<option::Option<oracle_data::Data<T>>>
+
+
+
+
+
+
+## Function `threshold`
+
+
+
+public fun threshold<T>(meta: &oracle_meta::MetaOracle<T>): u64
+
+
+
+
+
+
+## Function `time_window_ms`
+
+
+
+public fun time_window_ms<T>(meta: &oracle_meta::MetaOracle<T>): u64
+
+
+
+
+
+
+## Function `ticker`
+
+
+
+public fun ticker<T>(meta: &oracle_meta::MetaOracle<T>): string::String
+
+
+
+
+
+
+## Function `max_timestamp`
+
+
+
+public fun max_timestamp<T>(meta: &oracle_meta::MetaOracle<T>): u64
+
+
+
+
+
+
+## Function `value`
+
+
+
+public fun value<T>(data: &oracle_meta::TrustedData<T>): &T
+
+
+
+
+
+
+## Function `oracles`
+
+
+
+public fun oracles<T>(data: &oracle_meta::TrustedData<T>): vector<address>
+
diff --git a/frameworks/rooch-framework/doc/transaction_fee.md b/frameworks/rooch-framework/doc/transaction_fee.md
index da401fbabd..69602342b8 100644
--- a/frameworks/rooch-framework/doc/transaction_fee.md
+++ b/frameworks/rooch-framework/doc/transaction_fee.md
@@ -61,7 +61,7 @@ Returns the gas factor of gas.
-public fun calculate_gas(gas_amount: u64): u256
+public fun calculate_gas(gas_amount: u64): u256
@@ -72,7 +72,7 @@ Returns the gas factor of gas.
-public(friend) fun withdraw_fee(amount: u256): coin::Coin<gas_coin::GasCoin>
+public(friend) fun withdraw_fee(amount: u256): coin::Coin<gas_coin::GasCoin>
diff --git a/frameworks/rooch-framework/doc/transfer.md b/frameworks/rooch-framework/doc/transfer.md
index 3e053e2dad..cc402ec366 100644
--- a/frameworks/rooch-framework/doc/transfer.md
+++ b/frameworks/rooch-framework/doc/transfer.md
@@ -46,7 +46,7 @@ Transfer amount
of coins CoinType
from fromCoinType
to have key
and store
abilities.
-public entry fun transfer_coin<CoinType: store, key>(from: &signer, to: address, amount: u256)
+public entry fun transfer_coin<CoinType: store, key>(from: &signer, to: address, amount: u256)
@@ -58,7 +58,7 @@ This public entry function requires the CoinType
to have key<
Transfer amount
of coins CoinType
from from
to a Bitcoin Address.
-public entry fun transfer_coin_to_bitcoin_address<CoinType: store, key>(from: &signer, to: string::String, amount: u256)
+public entry fun transfer_coin_to_bitcoin_address<CoinType: store, key>(from: &signer, to: string::String, amount: u256)
@@ -72,7 +72,7 @@ The MultiChainAddress is represented by multichain_id
and raw
This public entry function requires the CoinType
to have key
and store
abilities.
-public entry fun transfer_coin_to_multichain_address<CoinType: store, key>(from: &signer, multichain_id: u64, raw_address: vector<u8>, amount: u256)
+public entry fun transfer_coin_to_multichain_address<CoinType: store, key>(from: &signer, multichain_id: u64, raw_address: vector<u8>, amount: u256)
diff --git a/frameworks/rooch-framework/sources/oracle/oracle.move b/frameworks/rooch-framework/sources/oracle/oracle.move
new file mode 100644
index 0000000000..a69fe56d37
--- /dev/null
+++ b/frameworks/rooch-framework/sources/oracle/oracle.move
@@ -0,0 +1,124 @@
+// Copyright (c) RoochNetwork
+// SPDX-License-Identifier: Apache-2.0
+
+module rooch_framework::oracle {
+ use std::option;
+ use std::option::Option;
+ use std::string;
+ use std::string::String;
+ use moveos_std::timestamp::now_milliseconds;
+ use moveos_std::tx_context::sender;
+ use moveos_std::object;
+ use moveos_std::object::Object;
+ use moveos_std::table::Table;
+ use moveos_std::table;
+
+ use rooch_framework::oracle_data::{Self, Data};
+
+ const ErrorSenderNotOracle: u64 = 0;
+ const ErrorTickerNotExists: u64 = 1;
+
+ struct TablePlaceholder has key {
+ _placeholder: bool,
+ }
+
+ struct SimpleOracle has store, key {
+ id: Object,
+ /// The address of the oracle.
+ address: address,
+ /// The name of the oracle.
+ name: String,
+ /// The description of the oracle.
+ description: String,
+ /// The URL of the oracle.
+ url: String,
+ }
+
+ struct StoredData has copy, store, drop {
+ value: T,
+ sequence_number: u64,
+ timestamp: u64,
+ /// An identifier for the reading (for example real time of observation, or sequence number of observation on other chain).
+ identifier: String,
+ }
+
+ public fun get_historical_data(
+ oracle_obj: &Object,
+ ticker: String,
+ archival_key: K
+ ): Option> {
+ let oracle = object::borrow(oracle_obj);
+ string::append(&mut string::utf8(b"[historical] "), ticker);
+ let historical_data: &Table> = object::borrow_field(&oracle.id, ticker);
+ let StoredData { value, sequence_number, timestamp, identifier } = *table::borrow(
+ historical_data,
+ archival_key
+ );
+ option::some(oracle_data::new(value, ticker, sequence_number, timestamp, oracle.address, identifier))
+ }
+
+ public fun get_latest_data(oracle_obj: &Object, ticker: String): Option> {
+ let oracle = object::borrow(oracle_obj);
+ if (!object::contains_field(&oracle.id, ticker)) {
+ return option::none()
+ };
+ let data: &StoredData = object::borrow_field(&oracle.id, ticker);
+ let StoredData { value, sequence_number, timestamp, identifier } = *data;
+ option::some(oracle_data::new(value, ticker, sequence_number, timestamp, oracle.address, identifier))
+ }
+
+ /// Create a new shared SimpleOracle object for publishing data.
+ public entry fun create(name: String, url: String, description: String) {
+ let oracle = object::new(SimpleOracle { id: object::new(TablePlaceholder{_placeholder: false}), address: sender(), name, description, url });
+ object::to_shared(oracle)
+ }
+
+ public fun submit_data(
+ oracle_obj: &mut Object,
+ ticker: String,
+ value: T,
+ identifier: String,
+ ) {
+ let oracle = object::borrow_mut(oracle_obj);
+ assert!(oracle.address == sender(), ErrorSenderNotOracle);
+
+ let sequence_number = if (object::contains_field(&oracle.id, ticker)) {
+ let old_data: StoredData = object::remove_field(&mut oracle.id, ticker);
+ old_data.sequence_number + 1
+ }else {
+ 0
+ };
+
+ let new_data = StoredData {
+ value,
+ sequence_number,
+ timestamp: now_milliseconds(),
+ identifier,
+ };
+ object::add_field(&mut oracle.id, ticker, new_data);
+ }
+
+ public fun archive_data(
+ oracle_obj: &mut Object,
+ ticker: String,
+ archival_key: K,
+ ) {
+ let oracle = object::borrow_mut(oracle_obj);
+ assert!(oracle.address == sender(), ErrorSenderNotOracle);
+ assert!(object::contains_field(&oracle.id, ticker), ErrorTickerNotExists);
+
+ let latest_data: StoredData = *object::borrow_mut_field(&mut oracle.id, ticker);
+
+ string::append(&mut string::utf8(b"[historical] "), ticker);
+ if (!object::contains_field(&oracle.id, ticker)) {
+ let data_source = table::new>();
+ object::add_field(&mut oracle.id, ticker, data_source);
+ };
+ let historical_data: &mut Table> = object::borrow_mut_field(&mut oracle.id, ticker);
+ // Replace the old data in historical data if any.
+ if (table::contains(historical_data, archival_key)) {
+ table::remove(historical_data, archival_key);
+ };
+ table::add(historical_data, archival_key, latest_data);
+ }
+}
\ No newline at end of file
diff --git a/frameworks/rooch-framework/sources/oracle/oracle_data.move b/frameworks/rooch-framework/sources/oracle/oracle_data.move
new file mode 100644
index 0000000000..82f034118c
--- /dev/null
+++ b/frameworks/rooch-framework/sources/oracle/oracle_data.move
@@ -0,0 +1,52 @@
+// Copyright (c) RoochNetwork
+// SPDX-License-Identifier: Apache-2.0
+
+module rooch_framework::oracle_data {
+ use std::string::String;
+
+ struct Data has drop, copy {
+ value: T,
+ metadata: Metadata,
+ }
+
+ struct Metadata has drop, copy {
+ ticker: String,
+ sequence_number: u64,
+ timestamp: u64,
+ oracle: address,
+ /// An identifier for the reading (for example real time of observation, or sequence number of observation on other chain).
+ identifier: String,
+ }
+
+ public fun new(
+ value: T,
+ ticker: String,
+ sequence_number: u64,
+ timestamp: u64,
+ oracle: address,
+ identifier: String
+ ): Data {
+ Data {
+ value,
+ metadata: Metadata {
+ ticker,
+ sequence_number,
+ timestamp,
+ oracle,
+ identifier,
+ },
+ }
+ }
+
+ public fun value(data: &Data): &T {
+ &data.value
+ }
+
+ public fun oracle_address(data: &Data): &address {
+ &data.metadata.oracle
+ }
+
+ public fun timestamp(data: &Data): u64 {
+ data.metadata.timestamp
+ }
+}
\ No newline at end of file
diff --git a/frameworks/rooch-framework/sources/oracle/oracle_meta.move b/frameworks/rooch-framework/sources/oracle/oracle_meta.move
new file mode 100644
index 0000000000..2f42d5bf18
--- /dev/null
+++ b/frameworks/rooch-framework/sources/oracle/oracle_meta.move
@@ -0,0 +1,179 @@
+// Copyright (c) RoochNetwork
+// SPDX-License-Identifier: Apache-2.0
+
+module rooch_framework::oracle_meta {
+ use std::option;
+ use std::option::Option;
+ use std::string::String;
+ use std::vector;
+ use moveos_std::sort::quick_sort;
+ use rooch_framework::oracle;
+ use moveos_std::object::Object;
+
+ use rooch_framework::oracle_data::{Self, Data};
+ use rooch_framework::oracle::SimpleOracle;
+ #[test_only]
+ use moveos_std::decimal_value;
+ #[test_only]
+ use moveos_std::decimal_value::DecimalValue;
+
+
+ const ErrorValidDataSizeLessThanThreshold: u64 = 0;
+ const ErrorUnsupportedDataType: u64 = 1;
+
+ struct MetaOracle {
+ oracle_data: vector