move-langsui

Transfer coins in move package


I wrote a mov package in which anyone can mint token (very new to move)

module fungible_tokens::rcoin {
    use sui::coin::{Self, Coin, TreasuryCap};
    use sui::transfer;
    use sui::tx_context::{Self, TxContext};


    struct RCOIN has drop {}

    
    /// Register the RCOIN currency to acquire its `TreasuryCap`. Because
    /// this is a module initializer, it ensures the currency only gets
    /// registered once.
    fun init(witness: RCOIN, ctx: &mut TxContext) {
        // Get a treasury cap for the coin 
        let treasury_cap = coin::create_currency<RCOIN>(witness, 2, ctx);
        // Make it a share object so that anyone can mint
        transfer::share_object(treasury_cap)
    }


    public entry fun mint(
        treasury_cap: &mut TreasuryCap<RCOIN>, amount: u64, recipient: address, ctx: &mut TxContext
    ) {
        coin::mint_and_transfer(treasury_cap, amount, recipient, ctx)
    }
}

Now, I want to send the coins I have minted to a different address. Sui transfer only transfers an object/sui gas.

Can someone help me with this?


Solution

  • This is how I was able to resolve it.

    
    
    // Copyright (c) Mysten Labs, Inc.
    // SPDX-License-Identifier: Apache-2.0
    
    /// Example coin with a trusted manager responsible for minting/burning (e.g., a stablecoin)
    /// By convention, modules defining custom coin types use upper case names, in contrast to
    /// ordinary modules, which use camel case.
    module fungible_tokens::r6coin {
        use sui::coin::{Self, Coin, TreasuryCap};
        use sui::transfer;
        use sui::pay;
        use sui::tx_context::{Self, TxContext};
        use std::vector;
        /// Name of the coin. By convention, this type has the same name as its parent module
        /// and has no fields. The full type of the coin defined by this module will be `COIN<R1COIN>`.
        struct R6COIN has drop {}
    
        /// For when empty vector is supplied into join function.
        const ENoCoins: u64 = 0;
        /// Register the RCOIN currency to acquire its `TreasuryCap`. Because
        /// this is a module initializer, it ensures the currency only gets
        /// registered once.
        fun init(witness: R6COIN, ctx: &mut TxContext) {
            // Get a treasury cap for the coin 
            let coin = coin::create_currency<R6COIN>(witness, 2, ctx);
            // Make it a share object so that anyone can mint
            transfer::share_object(coin)
        } 
    
        //     public entry fun mint(
        //     treasury_cap: &mut TreasuryCap<R1COIN>, amount: u64, recipient: address, ctx: &mut TxContext
        // ) {
        //     coin::mint_and_transfer(treasury_cap, amount, recipient, ctx)
        // }
    
        public entry fun join_split_transfer<T>(coins: vector<coin::Coin<T>>, amount: u64, recipient: address, ctx: &mut TxContext) {
              assert!(vector::length(&coins) > 0, ENoCoins);
                let coin = vector::pop_back(&mut coins);
                pay::join_vec(&mut coin, coins);
                pay::split_and_transfer<T>(&mut coin, amount, recipient, ctx);
                transfer::transfer(coin, tx_context::sender(ctx))
        }
    
        public entry fun mint(
            treasury_cap: &mut TreasuryCap<R6COIN>, amount: u64, recipient: address, ctx: &mut TxContext
        ) {
            coin::mint_and_transfer(treasury_cap, amount, recipient, ctx)
        }
    }
    

    In this code, look at this part

        public entry fun join_split_transfer<T>(coins: vector<coin::Coin<T>>, amount: u64, recipient: address, ctx: &mut TxContext) {
              assert!(vector::length(&coins) > 0, ENoCoins);
                let coin = vector::pop_back(&mut coins);
                pay::join_vec(&mut coin, coins);
                pay::split_and_transfer<T>(&mut coin, amount, recipient, ctx);
                transfer::transfer(coin, tx_context::sender(ctx))
        }
    

    Going line by line

    1. assert!(vector::length(&coins) > 0, ENoCoins); Here I am saying that there should be more than one coin object passed.

    Here, I am joining the coin objects

      let coin = vector::pop_back(&mut coins);
       pay::join_vec(&mut coin, coins);
    

    After joining the coin objects, I am calling SUI function which splits the amount and returns the remaining, the remaining is send back to the address.

          pay::split_and_transfer<T>(&mut coin, amount, recipient, ctx);
                transfer::transfer(coin, tx_context::sender(ctx))