Building Your First Magi Smart Contract: A Complete Guide!

Published on HivePostify by @tibfox · Tue Jan 20 2026

[](https://3speak.tv/watch?v=tibfox/ff9c946a)

▶️ [Watch on 3Speak](https://3speak.tv/watch?v=tibfox/ff9c946a)

---

You asked for a Magi contract tutorial from start to finish? I got you!

This tutorial walks through building a smart contract for the Magi network. We'll create a simple "flip" contract that randomly shuffles a list of possible values - useful for things like random selection, lottery draws, or simple day-to-day decisions :D

Should I do the dishes? Ask your own contract!

Before we jump right in I want to mention that the Magi chain is constantly in development and the tutorial could become outdated pretty soon. Make sure to check the official [contract-template repo](https://github.com/vsc-eco/go-contract-template) and the announcements of the Magi network for all the fresh SDK functions, news and possibilities. Also it is planned that there will be an SDK for other languages in near future so keep an eye out for that as well.

Big thanks to @techcoderx for his work and all the help he offered me while creating my first few contracts. Now let us jump in!

Setup

- [Go](https://go.dev/dl/) 1.24+ (Programing Language) - [TinyGo](https://tinygo.org/getting-started/install/) compiler (for WASM compilation) - [wasm tools](https://github.com/bytecodealliance/wasm-tools) or [wabt](https://github.com/WebAssembly/wabt) (For optimizing file size of your final contract wasm) - Basic understanding of Go programming (Don't be scared - it's simple)

Project Structure

In the video I will cover the flip contract. You can clone it from: https://github.com/tibfox/magicontracttutorialflip The video will not cover everything that is described here because this is a topic for another video.

After cloning the tutorial repo, you will find this structure:

magicontracttutorialflip/ ├── contract/ │ ├── main.go Main contract logic and exported functions │ └── random.go Randomization utilities ├── sdk/ │ ├── sdk.go Core SDK functions (state, logging, etc.) │ ├── env.go Environment/context types │ ├── address.go Address handling (Hive, EVM, etc.) │ └── asset.go Asset types (HIVE, HBD) ├── test/ │ └── contracttest.go Integration tests ├── artifacts/ │ └── main.wasm Compiled contract └── go.mod

Flow of the contract

Before we start to dive into the code I made this simple diagram to showcase the contract flow:

1. User executes the flip function providing a collection of possible results (a|b|c) 2. Contract randomizes the order using deterministic shuffling 3. Contract stores the result in state under a unique key based on transaction data 4. Contract emits the random order as an event log 5. Contract returns the storage key and shuffled result

---

Part 1: Cloning Contract Template

The Magi network provides an up-to-date [contract template](https://github.com/vsc-eco/go-contract-template) you can clone for your starting point. In this tutorial I will not go into details about it here as I assume you clone my [tutorial repo instead](https://github.com/tibfox/magicontracttutorialflip).

Part 2: Understanding the SDK

The SDK provides the interface between your contract and the Magi network. Make sure to always have the current sdk when developing a contract. Let's examine the key components of this folder.

Environment Context

When your contract executes, it receives context about the transaction via sdk.GetEnv():

go type Env struct { ContractId string // This contract's ID ContractOwner string // Owner address

TxId string // Transaction ID Index uint64 // Transaction index in block OpIndex uint64 // Operation index in transaction

BlockId string // Current block ID BlockHeight uint64 // Current block height Timestamp string // Block timestamp

Sender Sender // Who initiated this call Caller Address // Direct caller (could be another contract) }

The Sender contains authentication details but usually Sender.Address is enough for verifying permissions in your contract. The Caller is who actually called the contract function. That can be a user but also another contract. There can be a chain of up to 20 contracts but the original environment is always persistent so checking permissions can be made on the initial sender of the transaction.

go type Sender struct { Address Address // Sender's address RequiredAuths []Address // Active authority signers RequiredPostingAuths []Address // Posting authority signers }

Address Types

The network supports multiple address formats:

| Type | Prefix | Example | |------|--------|---------| | Hive | hive: | hive:username | | EVM | did:pkh:eip155 | did:pkh:eip155:1:0x... | | Contract | contract: | contract:abc123 | | System | system: | system:rewards |

For now I personally only made contracts that work with hive addresses and I assume that this list will increase with time.

Core SDK Functions

State Management: go sdk.StateSetObject(key, value string) // Store a value sdk.StateGetObject(key string) string // Retrieve a value sdk.StateDeleteObject(key string) // Remove a value

It is important to mention here that sdk.StateSetObject() is the most expensive single-call of the current system. Be mindful of that and try to allocate contract state as early as possible if you know how the state value will look like. Updates will become cheaper this way. Also try to minimize state value length by implementing mappings of known values (states, types and this kind of stuff) so you only store integers instead of whole strings. There are many ways to improve state usage but this depends highly on your use-case. Keep an eye out for my upcoming videos/posts about that topic.

Logging: go sdk.Log(message string) // Emit an log

This method can be used for simple logs but is also used to emit event logs for external indexers. More on that later.

Transaction Control: go sdk.Abort(msg string) // Hard abort

This will revert the whole contract call, revert fund movements and state interactions. It is smart to abort as early as possible to minimize ressources when the call fails and add a reason for the abort in the msg of course.

Asset Operations: go sdk.GetBalance(address Address, asset Asset) int64 // read the balance of a Magi address sdk.HiveDraw(amount int64, asset Asset) // Pull funds from the caller sdk.HiveTransfer(to Address, amount int64, asset Asset) // Sends funds from the contract sdk.HiveWithdraw(to Address, amount int64, asset Asset) // Unmap to Hive account

sdk.GetBalance(), sdk.HiveDraw() and sdk.HiveTransfer() are all operating on Magi itself while sdk.HiveWithdraw() will send funds from the contract to the receiver on the Hive blockchain.

Cross-Contract Calls: go sdk.ContractStateGet(contractId, key string) string sdk.ContractCall(contractId, method, payload string, options ContractCallOptions) string

These are super powerful tools where you can chain execute up to 20 contracts. For example you could create a task market platform/contract that calls my [escrow contract](https://ecency.com/hive-139531/@tibfox/kinoko-escrow-trust-made-simple) in order to create a secure trustless payment acknoledgement between two parties. No need to implement your own logic here. Also the contract we cover here can be used to find a random value out of multiple ones. You could just call this contract and save space/time for your own logic.

---

Part 3: Writing the Contract

The Main Entry Point

Every contract needs an empty main() function for WASM export to work:

go package main

Tags: #magi#tutorial#contract#wasm#vsc#basics

View full post on HivePostify →

Join HivePostify — Pakistan's First Web3 Platform →