Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(squid)!: squid object procurement #173

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
10 changes: 10 additions & 0 deletions move/squid/sources/squid/coin_bag.move
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ public(package) fun get_estimate<T>(self: &mut CoinBag): u64 {
}
}

public(package) fun get_exact_estimate<T>(self: &mut CoinBag, amount: u64) {
let key = get_estimate_key<T>();

assert!(self.bag.contains(key), EKeyNotExist);
let estimate = self.bag.borrow_mut<address, u64>(key);
assert!(*estimate >= amount, ENotEnoughBalance);

*estimate = *estimate - amount;
}

public(package) fun get_estimate_amount<T>(self: &CoinBag): u64 {
let key = get_estimate_key<T>();

Expand Down
8 changes: 4 additions & 4 deletions move/squid/sources/squid/deepbook_v3.move
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public fun estimate<B, Q>(
pool: &Pool<B, Q>,
clock: &Clock,
) {
let data = self.get_data_estimating();
if (data.length() == 0) return;
let (data, fallback) = self.get_data_estimating();
if (fallback) return;
let swap_data = peel_swap_data(data);

assert!(swap_data.swap_type == SWAP_TYPE, EWrongSwapType);
Expand Down Expand Up @@ -104,8 +104,8 @@ public fun swap<B, Q>(
clock: &Clock,
ctx: &mut TxContext,
) {
let data = self.get_data_swapping();
if (data.length() == 0) return;
let (data, fallback) = self.get_data_swapping();
if (fallback) return;
let swap_data = peel_swap_data(data);

assert!(swap_data.swap_type == SWAP_TYPE, EWrongSwapType);
Expand Down
25 changes: 20 additions & 5 deletions move/squid/sources/squid/discovery.move
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
module squid::discovery;

use its::its::ITS;
use std::ascii::{Self, String};

use sui::bcs;

use relayer_discovery::discovery::RelayerDiscovery;
use relayer_discovery::transaction::{Self, MoveCall, Transaction};

use its::its::ITS;

use squid::deepbook_v3;
use squid::squid::Squid;
use squid::transfers;
use std::ascii::{Self, String};
use sui::bcs;
use squid::object_procurement;

const EInvalidSwapType: u64 = 0;

const SWAP_TYPE_DEEPBOOK_V3: u8 = 1;
const SWAP_TYPE_SUI_TRANSFER: u8 = 2;
const SWAP_TYPE_ITS_TRANSFER: u8 = 3;
const SWAP_TYPE_OBJECT_PROCUREMENT: u8 = 4;

public fun register_transaction(
squid: &Squid,
Expand Down Expand Up @@ -91,15 +97,24 @@ public fun get_transaction(
swap_info_arg,
),
);
} else {
assert!(swap_type == SWAP_TYPE_ITS_TRANSFER, EInvalidSwapType);
} else if (swap_type == SWAP_TYPE_ITS_TRANSFER) {
move_calls.push_back(
transfers::get_its_estimate_move_call(
package_id,
bcs,
swap_info_arg,
),
);
} else if (swap_type == SWAP_TYPE_OBJECT_PROCUREMENT) {
move_calls.push_back(
object_procurement::get_estimate_move_call(
package_id,
bcs,
swap_info_arg,
),
);
} else {
abort(EInvalidSwapType)
};

i = i + 1;
Expand Down
182 changes: 182 additions & 0 deletions move/squid/sources/squid/object_procurement.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
module squid::object_procurement;

use relayer_discovery::transaction::{Self, MoveCall};
use squid::swap_info::SwapInfo;
use std::ascii::{Self, String};
use std::type_name;
use sui::bcs::{Self, BCS};
use sui::coin::Coin;

const SWAP_TYPE: u8 = 4;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a fan of partial declarations. define swap type enum in a separate type module and use it where needed?


// ------
// Errors
// ------
#[error]
const EWrongObject: vector<u8> =
b"object passed did not match the requested object";
#[error]
const ERemainingData: vector<u8> = b"remaining bcs data unexpected.";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const ERemainingData: vector<u8> = b"remaining bcs data unexpected.";
const ERemainingData: vector<u8> = b"remaining bcs data unexpected";

#[error]
const EWrongCoinType: vector<u8> = b"coin type mismatch.";
#[error]
const EWrongSwapType: vector<u8> = b"swap type mismatch.";
Comment on lines +21 to +23
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const EWrongCoinType: vector<u8> = b"coin type mismatch.";
#[error]
const EWrongSwapType: vector<u8> = b"swap type mismatch.";
const EWrongCoinType: vector<u8> = b"coin type mismatch";
#[error]
const EWrongSwapType: vector<u8> = b"swap type mismatch";


// -----
// Types
// -----
public struct ObjectProcurementSwapData {
swap_type: u8,
coin_type: String,
object_type: String,
object_id: ID,
recipient: address,
price: u64,
fallback: bool,
}

public fun estimate<T>(swap_info: &mut SwapInfo) {
let (data, fallback) = swap_info.get_data_estimating();

let swap_data = peel_swap_data(data, fallback);
assert!(swap_data.swap_type == SWAP_TYPE, EWrongSwapType);
assert!(
&swap_data.coin_type == &type_name::get<T>().into_string(),
EWrongCoinType,
);

if (!fallback) {
swap_info.coin_bag().get_exact_estimate<T>(swap_data.price);
};

swap_data.destroy();
}

public fun loan_coins<T>(
swap_info: &mut SwapInfo,
ctx: &mut TxContext,
): (ObjectProcurementSwapData, Option<Coin<T>>) {
let (data, fallback) = swap_info.get_data_swapping();

let swap_data = peel_swap_data(data, fallback);
assert!(swap_data.swap_type == SWAP_TYPE, EWrongSwapType);
assert!(
&swap_data.coin_type == &type_name::get<T>().into_string(),
EWrongCoinType,
);

if (fallback) return (swap_data, option::none());

let balance = swap_info.coin_bag().get_exact_balance<T>(swap_data.price);
let coin = balance.into_coin(ctx);
(swap_data, option::some(coin))
}

public fun return_object<T: key + store>(
swap_data: ObjectProcurementSwapData,
object_option: Option<T>,
) {
if (swap_data.fallback) {
object_option.destroy_none();
} else {
let object = object_option.destroy_some();
assert!(object::id(&object) == swap_data.object_id, EWrongObject);
transfer::public_transfer(object, swap_data.recipient);
};
swap_data.destroy();
}

public(package) fun get_estimate_move_call(
package_id: address,
mut bcs: BCS,
swap_info_arg: vector<u8>,
): MoveCall {
let coin_type = ascii::string(bcs.peel_vec_u8());

transaction::new_move_call(
transaction::new_function(
package_id,
ascii::string(b"object_procurement"),
ascii::string(b"estimate"),
),
vector[swap_info_arg],
vector[coin_type],
)
}

public(package) fun get_procure_move_call(
package_id: address,
mut bcs: BCS,
swap_info_arg: vector<u8>,
index: u8,
): vector<MoveCall> {
let coin_type = ascii::string(bcs.peel_vec_u8());
let object_type = ascii::string(bcs.peel_vec_u8());

let swap_data_arg = vector[4, index, 0];
let object_option_arg = vector[4, index + 1, 0];

let loan_call = transaction::new_move_call(
transaction::new_function(
package_id,
ascii::string(b"object_procurement"),
ascii::string(b"loan_coins"),
),
vector[swap_info_arg],
vector[coin_type],
);

let _object_id = bcs.peel_address();
let _recipient = bcs.peel_address();
let _price = bcs.peel_u64();

let purchase_call = transaction::new_move_call_from_bcs(&mut bcs);

assert!(bcs.into_remainder_bytes().length() == 0, ERemainingData);

let return_call = transaction::new_move_call(
transaction::new_function(
package_id,
ascii::string(b"object_procurement"),
ascii::string(b"return_object"),
),
vector[swap_data_arg, object_option_arg],
vector[object_type],
);
vector[loan_call, purchase_call, return_call]
}

// Store the fallback here too to be able to retreive in the `give_object`
fun peel_swap_data(
data: vector<u8>,
fallback: bool,
): ObjectProcurementSwapData {
let mut bcs = bcs::new(data);
let swap_data = ObjectProcurementSwapData {
swap_type: bcs.peel_u8(),
coin_type: ascii::string(bcs.peel_vec_u8()),
object_type: ascii::string(bcs.peel_vec_u8()),
object_id: object::id_from_address(bcs.peel_address()),
recipient: bcs.peel_address(),
price: bcs.peel_u64(),
fallback,
};

transaction::new_move_call_from_bcs(&mut bcs);

assert!(bcs.into_remainder_bytes().length() == 0, ERemainingData);

swap_data
}

fun destroy(self: ObjectProcurementSwapData) {
let ObjectProcurementSwapData {
swap_type: _,
object_id: _,
recipient: _,
coin_type: _,
object_type: _,
price: _,
fallback: _,
} = self;
}
13 changes: 9 additions & 4 deletions move/squid/sources/squid/squid.move
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
module squid::squid;

use axelar_gateway::channel::ApprovedMessage;
use its::its::ITS;
use squid::squid_v0::{Self, Squid_v0};
use squid::swap_info::SwapInfo;
use std::ascii;

use sui::clock::Clock;
use sui::versioned::{Self, Versioned};

use version_control::version_control::{Self, VersionControl};

use axelar_gateway::channel::ApprovedMessage;

use its::its::ITS;

use squid::squid_v0::{Self, Squid_v0};
use squid::swap_info::SwapInfo;

// -------
// Version
// -------
Expand Down
Loading
Loading