axelar-cgp-sui

Module 0xa9::its

use 0x1::ascii;
use 0x1::string;
use 0x1::type_name;
use 0x2::address;
use 0x2::clock;
use 0x2::coin;
use 0x2::event;
use 0x2::hex;
use 0x2::object;
use 0x2::sui;
use 0x2::transfer;
use 0x2::tx_context;
use 0xa1::channel;
use 0xa1::gateway;
use 0xa1::message_ticket;
use 0xa2::discovery;
use 0xa2::gas_service;
use 0xa2::transaction;
use 0xa5::coin_info;
use 0xa5::coin_management;
use 0xa5::discovery;
use 0xa5::interchain_transfer_ticket;
use 0xa5::its;
use 0xa5::token_id;
use 0xa9::utils;

Resource Singleton

struct Singleton has key
Fields
id: object::UID
channel: channel::Channel

Struct ExecutedWithToken

struct ExecutedWithToken has copy, drop
Fields
source_chain: ascii::String
source_address: vector<u8>
data: vector<u8>
amount: u64

Function init


Setup —–

fun init(ctx: &mut tx_context::TxContext)
Implementation
fun init(ctx: &mut TxContext) {
    let singletonId = object::new(ctx);
    let channel = channel::new(ctx);
    transfer::share_object(Singleton {
        id: singletonId,
        channel,
    });
}

Function register_transaction

This needs to be called to register the transaction so that the relayer knows to call this to fulfill calls.

public fun register_transaction(discovery: &mut discovery::RelayerDiscovery, singleton: &its::Singleton, its: &its::ITS, clock: &clock::Clock)
Implementation
public fun register_transaction(
    discovery: &mut RelayerDiscovery,
    singleton: &Singleton,
    its: &ITS,
    clock: &Clock,
) {
    let arguments = vector[
        concat(vector[0u8], object::id_address(singleton).to_bytes()),
        concat(vector[0u8], object::id_address(its).to_bytes()),
        vector[3u8],
        concat(vector[0u8], object::id_address(clock).to_bytes()),
    ];

    let transaction = transaction::new_transaction(
        false,
        vector[
            transaction::new_move_call(
                transaction::new_function(
                    address::from_bytes(
                        hex::decode(
                            *ascii::as_bytes(
                                &type_name::get_address(
                                    &type_name::get<Singleton>(),
                                ),
                            ),
                        ),
                    ),
                    ascii::string(b"its"),
                    ascii::string(b"get_final_transaction"),
                ),
                arguments,
                vector[],
            ),
        ],
    );

    discovery.register_transaction(&singleton.channel, transaction);
}

Function get_final_transaction

public fun get_final_transaction(singleton: &its::Singleton, its: &its::ITS, payload: vector<u8>, clock: &clock::Clock): transaction::Transaction
Implementation
public fun get_final_transaction(
    singleton: &Singleton,
    its: &ITS,
    payload: vector<u8>,
    clock: &Clock,
): Transaction {
    let arguments = vector[
        vector[2u8],
        concat(vector[0u8], object::id_address(singleton).to_bytes()),
        concat(vector[0u8], object::id_address(its).to_bytes()),
        concat(vector[0u8], object::id_address(clock).to_bytes()),
    ];

    // Get the coin type from its
    let (token_id, _, _, _) = its_discovery::interchain_transfer_info(
        payload,
    );
    let coin_type = (*its.registered_coin_type(token_id)).into_string();

    let transaction = transaction::new_transaction(
        true,
        vector[
            transaction::new_move_call(
                transaction::new_function(
                    address::from_bytes(
                        hex::decode(
                            *ascii::as_bytes(
                                &type_name::get_address(
                                    &type_name::get<Singleton>(),
                                ),
                            ),
                        ),
                    ),
                    ascii::string(b"its"),
                    ascii::string(b"receive_interchain_transfer"),
                ),
                arguments,
                vector[coin_type],
            ),
        ],
    );

    transaction
}

Function register_coin

This function needs to be called first to register the coin for either of the other two functions to work.

public fun register_coin<TOKEN>(its: &mut its::ITS, coin_metadata: &coin::CoinMetadata<TOKEN>): token_id::TokenId
Implementation
public fun register_coin<TOKEN>(
    its: &mut ITS,
    coin_metadata: &CoinMetadata<TOKEN>,
): TokenId {
    let coin_info = coin_info::from_info<TOKEN>(
        coin_metadata.get_name(),
        coin_metadata.get_symbol(),
        coin_metadata.get_decimals(),
        coin_metadata.get_decimals(),
    );
    let coin_management = coin_management::new_locked();

    its.register_coin(
        coin_info,
        coin_management,
    )
}

Function deploy_remote_interchain_token

public fun deploy_remote_interchain_token<TOKEN>(its: &mut its::ITS, gateway: &mut gateway::Gateway, gas_service: &mut gas_service::GasService, destination_chain: ascii::String, token_id: token_id::TokenId, gas: coin::Coin<sui::SUI>, gas_params: vector<u8>, refund_address: address)
Implementation
public fun deploy_remote_interchain_token<TOKEN>(
    its: &mut ITS,
    gateway: &mut Gateway,
    gas_service: &mut GasService,
    destination_chain: String,
    token_id: TokenId,
    gas: Coin<SUI>,
    gas_params: vector<u8>,
    refund_address: address,
) {
    let message_ticket = its.deploy_remote_interchain_token<TOKEN>(
        token_id,
        destination_chain,
    );

    pay_gas_and_send_message(
        gateway,
        gas_service,
        gas,
        message_ticket,
        refund_address,
        gas_params,
    );
}

Function send_interchain_transfer_call

This should trigger an interchain trasnfer.

public fun send_interchain_transfer_call<TOKEN>(singleton: &its::Singleton, its: &mut its::ITS, gateway: &mut gateway::Gateway, gas_service: &mut gas_service::GasService, token_id: token_id::TokenId, coin: coin::Coin<TOKEN>, destination_chain: ascii::String, destination_address: vector<u8>, metadata: vector<u8>, refund_address: address, gas: coin::Coin<sui::SUI>, gas_params: vector<u8>, clock: &clock::Clock)
Implementation
public fun send_interchain_transfer_call<TOKEN>(
    singleton: &Singleton,
    its: &mut ITS,
    gateway: &mut Gateway,
    gas_service: &mut GasService,
    token_id: TokenId,
    coin: Coin<TOKEN>,
    destination_chain: String,
    destination_address: vector<u8>,
    metadata: vector<u8>,
    refund_address: address,
    gas: Coin<SUI>,
    gas_params: vector<u8>,
    clock: &Clock,
) {
    let interchain_transfer_ticket = its::prepare_interchain_transfer<TOKEN>(
        token_id,
        coin,
        destination_chain,
        destination_address,
        metadata,
        &singleton.channel,
    );

    let message_ticket = its.send_interchain_transfer<TOKEN>(
        interchain_transfer_ticket,
        clock,
    );

    pay_gas_and_send_message(
        gateway,
        gas_service,
        gas,
        message_ticket,
        refund_address,
        gas_params,
    );
}

Function receive_interchain_transfer

This should receive some coins, give them to the executor, and emit and event with all the relevant info.

public fun receive_interchain_transfer<TOKEN>(approved_message: channel::ApprovedMessage, singleton: &its::Singleton, its: &mut its::ITS, clock: &clock::Clock, ctx: &mut tx_context::TxContext)
Implementation
public fun receive_interchain_transfer<TOKEN>(
    approved_message: ApprovedMessage,
    singleton: &Singleton,
    its: &mut ITS,
    clock: &Clock,
    ctx: &mut TxContext,
) {
    let (
        source_chain,
        source_address,
        data,
        coin,
    ) = its.receive_interchain_transfer_with_data<TOKEN>(
        approved_message,
        &singleton.channel,
        clock,
        ctx,
    );

    event::emit(ExecutedWithToken {
        source_chain,
        source_address,
        data,
        amount: coin.value(),
    });

    // give the coin to the caller
    transfer::public_transfer(coin, ctx.sender());
}

Function pay_gas_and_send_message

fun pay_gas_and_send_message(gateway: &gateway::Gateway, gas_service: &mut gas_service::GasService, gas: coin::Coin<sui::SUI>, message_ticket: message_ticket::MessageTicket, refund_address: address, gas_params: vector<u8>)
Implementation
fun pay_gas_and_send_message(
    gateway: &Gateway,
    gas_service: &mut GasService,
    gas: Coin<SUI>,
    message_ticket: MessageTicket,
    refund_address: address,
    gas_params: vector<u8>,
) {
    gas_service.pay_gas(
        gas,
        message_ticket.source_id(),
        message_ticket.destination_chain(),
        message_ticket.destination_address(),
        message_ticket.payload(),
        refund_address,
        gas_params,
    );

    gateway::send_message(gateway, message_ticket);
}