wugnot.gno

package wugnot

import (
	"chain"
	"chain/banker"
	"chain/runtime"
	"strings"

	"gno.land/p/demo/tokens/grc20"
	"gno.land/p/nt/ufmt/v0"
	"gno.land/r/demo/defi/grc20reg"
)

var Token, adm = grc20.NewToken("wrapped GNOT", "wugnot", 0)

const (
	ugnotMinDeposit  int64 = 1000
	wugnotMinDeposit int64 = 1
)

func init() {
	grc20reg.Register(cross, Token, "")
}

func Deposit(cur realm) {
	// Prevent cross-realm MITM: without this, an intermediary could
	// deposit on behalf of the caller and mint wugnot to itself
	// instead of the actual sender.
	runtime.AssertOriginCall()
	caller := runtime.PreviousRealm().Address()
	sent := banker.OriginSend()
	amount := sent.AmountOf("ugnot")

	require(int64(amount) >= ugnotMinDeposit, ufmt.Sprintf("Deposit below minimum: %d/%d ugnot.", amount, ugnotMinDeposit))

	checkErr(adm.Mint(caller, int64(amount)))
}

func Withdraw(cur realm, amount int64) {
	runtime.AssertOriginCall()
	require(amount >= wugnotMinDeposit, ufmt.Sprintf("Deposit below minimum: %d/%d wugnot.", amount, wugnotMinDeposit))

	caller := runtime.PreviousRealm().Address()
	pkgaddr := runtime.CurrentRealm().Address()
	callerBal := Token.BalanceOf(caller)
	require(amount <= callerBal, ufmt.Sprintf("Insufficient balance: %d available, %d needed.", callerBal, amount))

	// send swapped ugnots to qcaller
	stdBanker := banker.NewBanker(banker.BankerTypeRealmSend)
	send := chain.Coins{{"ugnot", int64(amount)}}
	stdBanker.SendCoins(pkgaddr, caller, send)
	checkErr(adm.Burn(caller, amount))
}

func Render(path string) string {
	parts := strings.Split(path, "/")
	c := len(parts)

	switch {
	case path == "":
		return Token.RenderHome()
	case c == 2 && parts[0] == "balance":
		owner := address(parts[1])
		balance := Token.BalanceOf(owner)
		return ufmt.Sprintf("%d", balance)
	default:
		return "404"
	}
}

func TotalSupply() int64 {
	return Token.TotalSupply()
}

func BalanceOf(owner address) int64 {
	return Token.BalanceOf(owner)
}

func Allowance(owner, spender address) int64 {
	return Token.Allowance(owner, spender)
}

func Transfer(cur realm, to address, amount int64) {
	userTeller := Token.CallerTeller()
	checkErr(userTeller.Transfer(to, amount))
}

func Approve(cur realm, spender address, amount int64) {
	userTeller := Token.CallerTeller()
	checkErr(userTeller.Approve(spender, amount))
}

func TransferFrom(cur realm, from, to address, amount int64) {
	userTeller := Token.CallerTeller()
	checkErr(userTeller.TransferFrom(from, to, amount))
}

func require(condition bool, msg string) {
	if !condition {
		panic(msg)
	}
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}