Skip to content

Commit

Permalink
[framework] Refactor result, make the error as generics (#2416)
Browse files Browse the repository at this point in the history
  • Loading branch information
jolestar authored Aug 12, 2024
1 parent 409638d commit 4e7f069
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 72 deletions.
40 changes: 21 additions & 19 deletions frameworks/rooch-nursery/doc/result.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [Function `is_ok`](#0xa_result_is_ok)
- [Function `get`](#0xa_result_get)
- [Function `err`](#0xa_result_err)
- [Function `err_string`](#0xa_result_err_string)
- [Function `err_str`](#0xa_result_err_str)
- [Function `is_err`](#0xa_result_is_err)
- [Function `get_err`](#0xa_result_get_err)
- [Function `as_err`](#0xa_result_as_err)
Expand All @@ -38,7 +38,7 @@ Most of the time, we do not need the Result type in smart contract, we can direc
But in some cases, we need to return a result to ensure the caller can handle the error.


<pre><code><b>struct</b> <a href="result.md#0xa_result_Result">Result</a>&lt;T&gt; <b>has</b> <b>copy</b>, drop
<pre><code><b>struct</b> <a href="result.md#0xa_result_Result">Result</a>&lt;T, E&gt; <b>has</b> <b>copy</b>, drop
</code></pre>


Expand Down Expand Up @@ -74,7 +74,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_ok">ok</a>&lt;T&gt;(value: T): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_ok">ok</a>&lt;T, E&gt;(value: T): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;
</code></pre>


Expand All @@ -85,7 +85,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_ok">is_ok</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): bool
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_ok">is_ok</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): bool
</code></pre>


Expand All @@ -96,7 +96,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get">get</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): &<a href="_Option">option::Option</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get">get</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): &<a href="_Option">option::Option</a>&lt;T&gt;
</code></pre>


Expand All @@ -107,18 +107,20 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err">err</a>&lt;T&gt;(err: <a href="">vector</a>&lt;u8&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err">err</a>&lt;T, E&gt;(err: E): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;
</code></pre>



<a name="0xa_result_err_string"></a>
<a name="0xa_result_err_str"></a>

## Function `err_string`
## Function `err_str`

A shortcut to create a Result<T, String> with an error String with
err_str(b"msg").


<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err_string">err_string</a>&lt;T&gt;(err: <a href="_String">string::String</a>): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err_str">err_str</a>&lt;T&gt;(err: <a href="">vector</a>&lt;u8&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, <a href="_String">string::String</a>&gt;
</code></pre>


Expand All @@ -129,7 +131,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_err">is_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): bool
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_err">is_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): bool
</code></pre>


Expand All @@ -140,7 +142,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get_err">get_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="_Option">option::Option</a>&lt;<a href="_String">string::String</a>&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get_err">get_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): &<a href="_Option">option::Option</a>&lt;E&gt;
</code></pre>


Expand All @@ -149,10 +151,10 @@ Expected the result is ok but the result is err.

## Function `as_err`

Convert an error Result<T> to error Result<U>.
Convert an error Result<T, String> to error Result<U, String>.


<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_as_err">as_err</a>&lt;U, T&gt;(self: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;U&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_as_err">as_err</a>&lt;U, T&gt;(self: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, <a href="_String">string::String</a>&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;U, <a href="_String">string::String</a>&gt;
</code></pre>


Expand All @@ -163,7 +165,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unpack">unpack</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): (<a href="_Option">option::Option</a>&lt;T&gt;, <a href="_Option">option::Option</a>&lt;<a href="_String">string::String</a>&gt;)
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unpack">unpack</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): (<a href="_Option">option::Option</a>&lt;T&gt;, <a href="_Option">option::Option</a>&lt;E&gt;)
</code></pre>


Expand All @@ -174,7 +176,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_and_then">and_then</a>&lt;U, T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;U&gt;, f: |U|<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_and_then">and_then</a>&lt;U, T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;U, E&gt;, f: |U|<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;
</code></pre>


Expand All @@ -185,7 +187,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap">unwrap</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): T
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap">unwrap</a>&lt;T, E: drop&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): T
</code></pre>


Expand All @@ -196,7 +198,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap_err">unwrap_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="_String">string::String</a>
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap_err">unwrap_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): E
</code></pre>


Expand All @@ -211,7 +213,7 @@ This function is inline, so it will be expanded in the caller.
This ensures the abort_code is the caller's location.


<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_ok">assert_ok</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;, abort_code: u64): T
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_ok">assert_ok</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;, abort_code: u64): T
</code></pre>


Expand All @@ -222,5 +224,5 @@ This ensures the abort_code is the caller's location.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_err">assert_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;, abort_code: u64): <a href="_String">string::String</a>
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_err">assert_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;, abort_code: u64): E
</code></pre>
2 changes: 1 addition & 1 deletion frameworks/rooch-nursery/doc/tick_info.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ Check if the tick is deployed.



<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="tick_info.md#0xa_tick_info_mint_on_bitcoin">mint_on_bitcoin</a>(metaprotocol: <a href="_String">string::String</a>, tick: <a href="_String">string::String</a>, amount: u64): <a href="result.md#0xa_result_Result">result::Result</a>&lt;<a href="_Object">object::Object</a>&lt;<a href="bitseed.md#0xa_bitseed_Bitseed">bitseed::Bitseed</a>&gt;&gt;
<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="tick_info.md#0xa_tick_info_mint_on_bitcoin">mint_on_bitcoin</a>(metaprotocol: <a href="_String">string::String</a>, tick: <a href="_String">string::String</a>, amount: u64): <a href="result.md#0xa_result_Result">result::Result</a>&lt;<a href="_Object">object::Object</a>&lt;<a href="bitseed.md#0xa_bitseed_Bitseed">bitseed::Bitseed</a>&gt;, <a href="_String">string::String</a>&gt;
</code></pre>


Expand Down
42 changes: 21 additions & 21 deletions frameworks/rooch-nursery/sources/inscribe_factory.move
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module rooch_nursery::inscribe_factory {

use rooch_nursery::bitseed::{Self, Bitseed};
use rooch_nursery::tick_info;
use rooch_nursery::result::{Self, Result, err, ok, is_err, as_err};
use rooch_nursery::result::{Self, Result, err_str, ok, is_err, as_err};

const BIT_SEED_DEPLOY: vector<u8> = b"bitseed_deploy";
const BIT_SEED_MINT: vector<u8> = b"bitseed_mint";
Expand Down Expand Up @@ -138,25 +138,25 @@ module rooch_nursery::inscribe_factory {
return option::none()
}

fun is_valid_bitseed(metadata: &SimpleMap<String,vector<u8>>) : Result<bool> {
fun is_valid_bitseed(metadata: &SimpleMap<String,vector<u8>>) : Result<bool,String> {
let tick = get_SFT_tick_option(metadata);
if (option::is_none(&tick)) {
return err(b"metadata.tick is required")
return err_str(b"metadata.tick is required")
};

let tick_len = std::string::length(option::borrow(&tick));
if (tick_len < 4 || tick_len > 32) {
return err(b"metadata.tick must be 4-32 characters")
return err_str(b"metadata.tick must be 4-32 characters")
};

let amount = get_SFT_amount_option(metadata);
if (option::is_none(&amount)) {
return err(b"metadata.amount is required")
return err_str(b"metadata.amount is required")
};
ok(true)
}

fun is_valid_bitseed_deploy(metadata: &SimpleMap<String,vector<u8>>) : Result<bool> {
fun is_valid_bitseed_deploy(metadata: &SimpleMap<String,vector<u8>>) : Result<bool,String> {
let is_valid_result = is_valid_bitseed(metadata);
if (is_err(&is_valid_result)) {
return is_valid_result
Expand All @@ -168,12 +168,12 @@ module rooch_nursery::inscribe_factory {
let factory = get_SFT_string_attribute(&attributes, b"factory");
if (option::is_none(&generator) && option::is_none(&factory)) {
simple_map::drop(attributes);
return err(b"metadata.attributes.generator or metadata.attributes.factory is required")
return err_str(b"metadata.attributes.generator or metadata.attributes.factory is required")
};

if (option::is_some(&generator) && option::is_some(&factory)) {
simple_map::drop(attributes);
return err(b"metadata.attributes.generator and metadata.attributes.factory can not exist at the same time")
return err_str(b"metadata.attributes.generator and metadata.attributes.factory can not exist at the same time")
};
if (option::is_some(&generator)) {
let is_valid_result= is_valid_generator_uri(option::borrow(&generator));
Expand All @@ -190,37 +190,37 @@ module rooch_nursery::inscribe_factory {
ok(true)
}

fun is_valid_generator_uri(generator_uri: &String) : Result<bool> {
fun is_valid_generator_uri(generator_uri: &String) : Result<bool,String> {
let index = string::index_of(generator_uri, &std::string::utf8(b"/inscription/"));
if (index != 0) {
return err(b"metadata.attributes.generator not start with /inscription/")
return err_str(b"metadata.attributes.generator not start with /inscription/")
};

let inscription_id_str = string::sub_string(generator_uri, vector::length(&b"/inscription/"), string::length(generator_uri));
let inscription_id_option = ord::parse_inscription_id(&inscription_id_str);
if (option::is_none(&inscription_id_option)) {
return err(b"metadata.attributes.generator inscription_id parse fail")
return err_str(b"metadata.attributes.generator inscription_id parse fail")
};

let inscription_id = option::extract(&mut inscription_id_option);
if (!ord::exists_inscription(inscription_id)) {
return err(b"metadata.attributes.generator inscription not exists")
return err_str(b"metadata.attributes.generator inscription not exists")
};

if (!ord::exists_metaprotocol_validity(inscription_id)) {
return err(b"metadata.attributes.generator inscription metaprotocol validity not exists")
return err_str(b"metadata.attributes.generator inscription metaprotocol validity not exists")
};

let metaprotocol_validity = ord::borrow_metaprotocol_validity(inscription_id);

let is_match = ord::metaprotocol_validity_protocol_match<Bitseed>(metaprotocol_validity);
if (!is_match) {
return err(b"metadata.attributes.generator inscription metaprotocol validity protocol not match")
return err_str(b"metadata.attributes.generator inscription metaprotocol validity protocol not match")
};

let is_valid = ord::metaprotocol_validity_is_valid(metaprotocol_validity);
if (!is_valid) {
return err(b"metadata.attributes.generator inscription metaprotocol validity not valid")
return err_str(b"metadata.attributes.generator inscription metaprotocol validity not valid")
};
ok(true)
}
Expand Down Expand Up @@ -264,7 +264,7 @@ module rooch_nursery::inscribe_factory {
(true, option::none<String>())
}

fun mint_bitseed(metadata: &SimpleMap<String,vector<u8>>, seed: vector<u8>, content_type: Option<String>, body: vector<u8>) : Result<Object<Bitseed>> {
fun mint_bitseed(metadata: &SimpleMap<String,vector<u8>>, seed: vector<u8>, content_type: Option<String>, body: vector<u8>) : Result<Object<Bitseed>,String> {
let is_valid_result = is_valid_bitseed(metadata);
if (is_err(&is_valid_result)) {
return as_err(is_valid_result)
Expand All @@ -276,7 +276,7 @@ module rooch_nursery::inscribe_factory {

if (!tick_info::is_deployed(bitseed::metaprotocol(), tick)) {
simple_map::drop(attributes);
return err(b"the tick is not deployed")
return err_str(b"the tick is not deployed")
};
let tick_info = tick_info::borrow_tick_info(bitseed::metaprotocol(), tick);
let has_user_input = tick_info::has_user_input(tick_info);
Expand All @@ -288,7 +288,7 @@ module rooch_nursery::inscribe_factory {
let user_input_option = get_SFT_string_attribute(&attributes, b"id");
if (option::is_none(&user_input_option)) {
simple_map::drop(attributes);
return err(b"metadata.attributes.user_input is required")
return err_str(b"metadata.attributes.user_input is required")
};

user_input = *option::borrow(&user_input_option);
Expand All @@ -298,13 +298,13 @@ module rooch_nursery::inscribe_factory {
let generator_inscription_id_option = tick_info::generator(tick_info);
if (option::is_none(&generator_inscription_id_option)) {
simple_map::drop(attributes);
return err(b"the tick can not mint on Bitcoin")
return err_str(b"the tick can not mint on Bitcoin")
};

let generator_inscription_id = option::destroy_some(generator_inscription_id_option);
if (!ord::exists_metaprotocol_validity(generator_inscription_id)) {
simple_map::drop(attributes);
return err(b"generator_inscription_id is not validity bitseed")
return err_str(b"generator_inscription_id is not validity bitseed")
};

let generator_txid = ord::inscription_id_txid(&generator_inscription_id);
Expand All @@ -317,7 +317,7 @@ module rooch_nursery::inscribe_factory {
let (is_valid, reason) = inscribe_verify(wasm_bytes, deploy_args, seed, user_input, metadata, content_type, body);
if (!is_valid) {
simple_map::drop(attributes);
return result::err_string(option::destroy_with_default(reason, utf8(b"inscribe verify fail")))
return result::err(option::destroy_with_default(reason, utf8(b"inscribe verify fail")))
};
};
let bitseed_result = tick_info::mint_on_bitcoin(bitseed::metaprotocol(), tick, amount);
Expand Down
Loading

0 comments on commit 4e7f069

Please sign in to comment.