# Joining two coins of custom currency

**URL:** <https://forums.sui.io/t/joining-two-coins-of-custom-currency/48952>\
**Category:** Move\
**Created:** [July 30, 2025, 10:40am UTC](https://forums.sui.io/t/joining-two-coins-of-custom-currency/48952 "2025-07-30T10:40:40Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![plyoteo](https://avatars.discourse-cdn.com/v4/letter/p/838e76/32.png) [@plyoteo](https://forums.sui.io/u/plyoteo)\
**Post date:** [July 30, 2025, 10:40am UTC](https://forums.sui.io/t/joining-two-coins-of-custom-currency/48952/1 "2025-07-30T10:40:40Z")

</div>

Hello SUI Move comrades. Please lend me a helping hand if you will. I am creating a currency of mine, minting it, splitting it and burning it as per code below:

```
      module try_nft::dnr;
                  
      const COIN_URL: vector<u8> = b"xyz";
        
      use sui::coin::{Self, Coin, TreasuryCap};
      use sui::url;
        
      public struct DNR has drop {}
        
      fun init(witness: DNR, ctx: &mut TxContext) {
          let (treasury_cap, metadata) = coin::create_currency<DNR>(
              witness,
              9,
              b"My SUI Coin",
              b"Denero",
              b"Coin worth crickets",
              option::some(url::new_unsafe_from_bytes(COIN_URL)),
              ctx,
          );
        
          transfer::public_freeze_object(metadata);
          transfer::public_transfer(treasury_cap, tx_context::sender(ctx));
      }
        
      public entry fun mint_coin(
          treasury_cap: &mut TreasuryCap<DNR>,
          amount: u64,
          recipient: address,
          ctx: &mut TxContext) {
              coin::mint_and_transfer(treasury_cap, amount, recipient, ctx);
      }
        
      public entry fun burn_coin(
          treasury_cap: &mut TreasuryCap<DNR>,
          coin: Coin<DNR>) {
              coin::burn(treasury_cap, coin);
      }
        
      public entry fun split_coin(
          self: &mut Coin<DNR>,
          amount: u64,
          recipient: address,
          ctx: & mut TxContext) {
              let new_split_coin = coin::split(self, amount, ctx);
              transfer::public_transfer(new_split_coin, recipient);
      }

```

It compiles just fine and works as a peach when tested on SuiScan. However, when I try to join the two splitted coins, with the snippet below,

```
      public entry fun join_coin(
          self: &mut Coin<DNR>,
          c: Coin<DNR>,
          recipient: address) {
              let new_join_coin = coin::join(self, c);
              transfer::public_transfer(new_join_coin, recipient);
      }

```

I get a compilation error as below,

error[E04005]: expected a single type  
┌─ ./sources/try\_nft.move:61:13  
│  
61 │ let new\_join\_coin = coin::join(self, c);  
│ ^^^^^^^^^^^^^ Invalid type for local  
│  
┌─ /home/plyoteo/.move/https\_\_\_github\_com\_MystenLabs\_sui\_git\_2c930c25f8d3/crates/sui-framework/packages/sui-framework/sources/coin.move:165:18  
│  
165 │ public entry fun join(self: &mut Coin, c: Coin) {  
│ ---- Expected a single type, but found expression list type: ‘()’

Any ideas? I think that I am using the join fun exactly as outlined in sui:🪙:join documentation.

I thank you in advance

---

<div class="post-metadata">

**Author:** ![DevDanny](https://avatars.discourse-cdn.com/v4/letter/d/ecae2f/32.png) [@DevDanny](https://forums.sui.io/u/DevDanny)\
**Post date:** [August 1, 2025, 4:42pm UTC](https://forums.sui.io/t/joining-two-coins-of-custom-currency/48952/2 "2025-08-01T16:42:51Z")

</div>

# Understanding the Coin Join and Transfer in SUI Move

## The Problem

The original implementation had two key issues:

1. Misunderstanding of `coin::join`’s return value (it returns `()`)
2. Attempting to transfer a mutable reference (`&mut Coin`) which violates Sui’s ownership model

## Why the Original Code Failed

```move
public entry fun join_coin(
    self: &mut Coin<DNR>,
    c: Coin<DNR>,
    recipient: address
) {
    let new_join_coin = coin::join(self, c); // Problem 1: No return value
    transfer::public_transfer(new_join_coin, recipient); // Problem 2: Can't transfer reference
}

```

Key problems:

1. `coin::join` modifies `self` in-place and doesn’t return a new coin
2. `public_transfer` requires an owned object with `key + store` abilities, not a reference

## Corrected Solutions

### Option 1: Simple Join (Recommended)

```move
public entry fun join_coins(
    coin1: &mut Coin<DNR>, // First coin to merge into
    coin2: Coin<DNR> // Second coin to be consumed
) {
    coin::join(coin1, coin2);
}

```

### Option 2: Join and Transfer

```move
public entry fun join_and_transfer(
    treasury_cap: &mut TreasuryCap<DNR>, // Needed for potential re-minting
    coin1: Coin<DNR>, // First coin (will be merged)
    coin2: Coin<DNR>, // Second coin (will be consumed)
    recipient: address,
    ctx: &mut TxContext
) {
    // Merge coins
    let mut merged_coin = coin1;
    coin::join(&mut merged_coin, coin2);
    
    // Transfer the merged coin
    transfer::public_transfer(merged_coin, recipient);
}

```

## Key Corrections and Insights

1. **Ownership Matters** :

2. **Proper Entry Function Design** :

## Important Notes

1. The `TreasuryCap` parameter in Option 2 is optional but recommended if you might need to mint/burn later

2. Always consider:

3. Remember that after transfer:

---

<div class="post-metadata">

**Author:** ![plyoteo](https://avatars.discourse-cdn.com/v4/letter/p/838e76/32.png) [@plyoteo](https://forums.sui.io/u/plyoteo)\
**Post date:** [August 1, 2025, 5:59pm UTC](https://forums.sui.io/t/joining-two-coins-of-custom-currency/48952/3 "2025-08-01T17:59:13Z")

</div>

DevDanny,

Thank you so much, both for the two solutions but mostly for the deep insights into the inner workings of move. I am a 63 yr old programming hobbyist coming from a Python/NodeJS background, so statically typed, compiled languages give me a bit of the chills. After working out the bare essential of Rust I took a head-first plunge into Move. Your response is probably a good reason I wont give up trying.

Thank you again,  
Theodoros

Στις Παρ 1 Αυγ 2025, 19:52 ο χρήστης DevDanny via Sui Developer Forum \<[notifications@sui.discoursemail.com](mailto:notifications@sui.discoursemail.com)\> έγραψε:
