# Your First Coin

This tutorial introduces how you can compile, deploy, and mint your own coin, named MoonCoin.

### Step 1: Pick an SDK[​](https://aptos.dev/tutorials/your-first-coin#step-1-pick-an-sdk) <a href="#step-1-pick-an-sdk" id="step-1-pick-an-sdk"></a>

Install your preferred SDK from the below list:

* [TypeScript SDK](https://aptos.dev/sdks/ts-sdk/index)
* [Python SDK](https://aptos.dev/sdks/python-sdk)
* [Rust SDK](https://aptos.dev/sdks/rust-sdk)

***

### Step 2: Install the CLI[​](https://aptos.dev/tutorials/your-first-coin#step-2-install-the-cli) <a href="#step-2-install-the-cli" id="step-2-install-the-cli"></a>

[Install the precompiled binary for the Aptos CLI](https://aptos.dev/cli-tools/aptos-cli-tool/install-aptos-cli).

***

### Step 3: Run the example[​](https://aptos.dev/tutorials/your-first-coin#step-3-run-the-example) <a href="#step-3-run-the-example" id="step-3-run-the-example"></a>

Clone the `aptos-core` repo:

```
git clone https://github.com/aptos-labs/aptos-core.git
```

* Typescript
* Python
* Rust

Navigate to the TypeScript SDK directory:

```
cd ~/aptos-core/ecosystem/typescript/sdk
```

Install the necessary dependencies:

```
yarn
```

Run the TypeScript [`your_coin`](https://github.com/aptos-labs/aptos-core/blob/main/ecosystem/typescript/sdk/examples/typescript/your_coin.ts) example:

```
yarn your_coin ~/aptos-core/aptos-move/move-examples/moon_coin
```

***

#### Step 3.1: Build the package[​](https://aptos.dev/tutorials/your-first-coin#step-31-build-the-package) <a href="#step-31-build-the-package" id="step-31-build-the-package"></a>

The example run will pause with the following output:

```
=== Addresses ===Alice: 0x5e603a89cf690d7134cf2f24fdb16ba90c4f5686333721c12e835fb6c76bc7baBob: 0xc8421fa4a99153f955e50f1de2a6acff2f3fd0bb33aa17ba1f5b32b699f6c825Update the package with Alice's address, compile, and press enter.
```

At this point, open another terminal and change directories to the MoonCoin package's directory:

```
cd ~/aptos-core/aptos-move/move-examples/moon_coin
```

Next, build the package using the CLI:

```
aptos move compile --named-addresses MoonCoin=0x5e603a89cf690d7134cf2f24fdb16ba90c4f5686333721c12e835fb6c76bc7ba --save-metadata
```

The `--named-addresses` is a list of address mappings that must be translated in order for the package to be compiled to be stored in Alice's account. Notice how `MoonCoin` is set to Alice's address printed above. Also `--save-metadata` is required to publish the package.

***

#### Step 3.2: Completing the example[​](https://aptos.dev/tutorials/your-first-coin#step-32-completing-the-example) <a href="#step-32-completing-the-example" id="step-32-completing-the-example"></a>

Returning to the previous prompt, press ENTER as the package is now ready to be published.

The application will complete, printing:

```
Publishing MoonCoin package.Bob registers the newly created coin so he can receive it from Alice.Bob's initial MoonCoin balance: 0.Alice mints Bob some of the new coin.Bob's updated MoonCoin balance: 100.
```

***

### Step 4: MoonCoin in depth[​](https://aptos.dev/tutorials/your-first-coin#step-4-mooncoin-in-depth) <a href="#step-4-mooncoin-in-depth" id="step-4-mooncoin-in-depth"></a>

#### Step 4.1: Building and publishing the MoonCoin package[​](https://aptos.dev/tutorials/your-first-coin#step-41-building-and-publishing-the-mooncoin-package) <a href="#step-41-building-and-publishing-the-mooncoin-package" id="step-41-building-and-publishing-the-mooncoin-package"></a>

Move contracts are effectively a set of Move modules known as a package. When deploying or upgrading a new package, the compiler must be invoked with `--save-metadata` to publish the package. In the case of MoonCoin, the following output files are critical:

* `build/Examples/package-metadata.bcs`: Contains the metadata associated with the package.
* `build/Examples/bytecode_modules/moon_coin.mv`: Contains the bytecode for the `moon_coin.move` module.

These are read by the example and published to the Aptos blockchain:

* Typescript
* Python
* Rust

```
const modulePath = process.argv[2];const packageMetadata = fs.readFileSync(path.join(modulePath, "build", "Examples", "package-metadata.bcs"));const moduleData = fs.readFileSync(path.join(modulePath, "build", "Examples", "bytecode_modules", "moon_coin.mv"));console.log("Publishing MoonCoin package.");let txnHash = await client.publishPackage(alice, new HexString(packageMetadata.toString("hex")).toUint8Array(), [  new TxnBuilderTypes.Module(new HexString(moduleData.toString("hex")).toUint8Array()),]);await client.waitForTransaction(txnHash, { checkSuccess: true }); 
```

***

#### Step 4.2: Understanding the MoonCoin module[​](https://aptos.dev/tutorials/your-first-coin#step-42-understanding-the-mooncoin-module) <a href="#step-42-understanding-the-mooncoin-module" id="step-42-understanding-the-mooncoin-module"></a>

The MoonCoin module defines the `MoonCoin` struct, or the distinct type of coin type. In addition, it contains a function called `init_module`. The `init_module` function is called when the module is published. In this case, MoonCoin initializes the `MoonCoin` coin type as a `ManagedCoin`, which is maintained by the owner of the account.

MANAGEDCOIN FRAMEWORK

[`ManagedCoin`](https://github.com/aptos-labs/aptos-core/blob/f81ccb01f00227f9c0f36856fead4879f185a9f6/aptos-move/framework/aptos-framework/sources/managed_coin.move#L1) is a simple coin management framework for coins directly managed by users. It provides convenience wrappers around `mint` and `burn`.

```
module MoonCoin::moon_coin {    struct MoonCoin {}    fun init_module(sender: &signer) {        aptos_framework::managed_coin::initialize<MoonCoin>(            sender,            b"Moon Coin",            b"MOON",            6,            false,        );    }}
```

***

#### Step 4.3: Understanding coins[​](https://aptos.dev/tutorials/your-first-coin#step-43-understanding-coins) <a href="#step-43-understanding-coins" id="step-43-understanding-coins"></a>

Coins have several primitives:

* **Minting**: Creating new coins.
* **Burning**: Deleting coins.
* **Freezing**: Preventing an account from storing coins in `CoinStore`.
* **Registering**: Creating a `CoinStore` resource on an account for storing coins.
* **Transferring**: Withdrawing and depositing coins into `CoinStore`.

TIP

The entity that creates a new coin gains the capabilities for minting, burning, and freezing.

In order to transfer, withdraw, or deposit coins, you must have a `CoinStore` registered for the specific coin. In this tutorial, this is `CoinStore<MoonCoin>`.

***

**Step 4.3.1: Initializing a coin**[**​**](https://aptos.dev/tutorials/your-first-coin#step-431-initializing-a-coin)

Once a coin type has been published to the Aptos blockchain, the entity that published that coin type can initialize it:

```
public fun initialize<CoinType>(    account: &signer,    name: string::String,    symbol: string::String,    decimals: u8,    monitor_supply: bool,): (BurnCapability<CoinType>, FreezeCapability<CoinType>, MintCapability<CoinType>) {    let account_addr = signer::address_of(account);    assert!(        coin_address<CoinType>() == account_addr,        error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH),    );    assert!(        !exists<CoinInfo<CoinType>>(account_addr),        error::already_exists(ECOIN_INFO_ALREADY_PUBLISHED),    );    let coin_info = CoinInfo<CoinType> {        name,        symbol,        decimals,        supply: if (monitor_supply) { option::some(optional_aggregator::new(MAX_U128, false)) } else { option::none() },    };    move_to(account, coin_info);    (BurnCapability<CoinType>{ }, FreezeCapability<CoinType>{ }, MintCapability<CoinType>{ })}
```

This ensures that this coin type has never been initialized before. Notice the check on lines 10 and 15 to ensure that the caller to `initialize` is the same one that actually published this module, and that there is no `CoinInfo` stored on their account. If both those conditions check, then a `CoinInfo` is stored and the caller obtains capabilities for burning, freezing, and minting.

TIP

MoonCoin calls this `initialize` function automatically upon package publishing.

***

**Step 4.3.2: Registering a coin**[**​**](https://aptos.dev/tutorials/your-first-coin#step-432-registering-a-coin)

To use a coin, an entity must register a `CoinStore` for it on their account:

```
public fun register<CoinType>(account: &signer) {    let account_addr = signer::address_of(account);    assert!(        !is_account_registered<CoinType>(account_addr),        error::already_exists(ECOIN_STORE_ALREADY_PUBLISHED),    );    account::register_coin<CoinType>(account_addr);    let coin_store = CoinStore<CoinType> {        coin: Coin { value: 0 },        frozen: false,        deposit_events: account::new_event_handle<DepositEvent>(account),        withdraw_events: account::new_event_handle<WithdrawEvent>(account),    };    move_to(account, coin_store);}
```

As this is a `public fun` and not a `public entry fun`, coins will need to provide their own means for registering or users can construct Move `scripts` to call the function.

MoonCoin uses `ManagedCoin` that provides an entry function wrapper: `managed_coin::register`.

***

**Step 4.3.3: Minting a coin**[**​**](https://aptos.dev/tutorials/your-first-coin#step-433-minting-a-coin)

Minting coins requires the mint capability that was produced during initialization. the function `mint` (see below) takes in that capability and an amount, and returns back a `Coin<T>` struct containing that amount of coins. If the coin tracks supply, it will be updated.

```
public fun mint<CoinType>(    amount: u64,    _cap: &MintCapability<CoinType>,): Coin<CoinType> acquires CoinInfo {    if (amount == 0) {        return zero<CoinType>()    };    let maybe_supply = &mut borrow_global_mut<CoinInfo<CoinType>>(coin_address<CoinType>()).supply;    if (option::is_some(maybe_supply)) {        let supply = option::borrow_mut(maybe_supply);        optional_aggregator::add(supply, (amount as u128));    };    Coin<CoinType> { value: amount }}
```

`ManagedCoin` makes this easier by providing a entry function `managed_coin::mint`.

***

**Step 4.3.4: Transferring a coin**[**​**](https://aptos.dev/tutorials/your-first-coin#step-434-transferring-a-coin)

Aptos provides several building blocks to support coin transfers:

* `coin::deposit<CoinType>`: Allows any entity to deposit a coin into an account that has already called `coin::register<CoinType>`.
* `coin::withdraw<CoinType>`: Allows any entity to extract a coin amount from their account.
* `coin::transfer<CoinType>`: Leverages withdraw and deposit to perform an end-to-end transfer.

IMPORTANT

Aptos does not emit transfer events, but instead it leverages withdraw and deposit events.

* [Aptos CLI](https://aptos.dev/cli-tools/aptos-cli-tool/use-aptos-cli)
* [TypeScript SDK](https://aptos.dev/sdks/ts-sdk/index)
* [Python SDK](https://aptos.dev/sdks/python-sdk)
* [Rust SDK](https://aptos.dev/sdks/rust-sdk)
* [REST API specification](https://fullnode.devnet.aptoslabs.com/v1/spec#/)
