diff --git a/examples/gno.land/r/demo/wugnot/gno.mod b/examples/gno.land/r/demo/wugnot/gno.mod new file mode 100644 index 00000000000..1f03ded515c --- /dev/null +++ b/examples/gno.land/r/demo/wugnot/gno.mod @@ -0,0 +1,6 @@ +module gno.land/r/demo/wugnot + +require ( + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest +) diff --git a/examples/gno.land/r/demo/wugnot/wugnot.gno b/examples/gno.land/r/demo/wugnot/wugnot.gno new file mode 100644 index 00000000000..82c3c43db89 --- /dev/null +++ b/examples/gno.land/r/demo/wugnot/wugnot.gno @@ -0,0 +1,126 @@ +package wugnot + +import ( + "std" + "strings" + + "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/ufmt" +) + +var ( + // wugnot is the admin token, able to mint and burn. + wugnot *grc20.AdminToken = grc20.NewAdminToken("wrapped GNOT", "wugnot", 0) + // WUGNOT is the banker usable by users directly. + WUGNOT = wugnot.GRC20() +) + +const ( + ugnotMinDeposit uint64 = 1000 + wugnotMinDeposit uint64 = 1 +) + +// wrapper. +// + +func Deposit() { + caller := std.PrevRealm().Addr() + sent := std.GetOrigSend() + amount := sent.AmountOf("ugnot") + + if uint64(amount) < ugnotMinDeposit { + panic(ufmt.Sprintf("Deposit below minimum: %d/%d ugnot.", amount, ugnotMinDeposit)) + } + wugnot.Mint(caller, uint64(amount)) +} + +func Withdraw(amount uint64) { + if amount < wugnotMinDeposit { + panic(ufmt.Sprintf("Deposit below minimum: %d/%d wugnot.", amount, wugnotMinDeposit)) + } + + caller := std.PrevRealm().Addr() + pkgaddr := std.GetOrigPkgAddr() + + callerBal, _ := wugnot.BalanceOf(caller) + if callerBal < amount { + panic(ufmt.Sprintf("Insufficient balance: %d available, %d needed.", callerBal, amount)) + } + + // send swapped ugnots to caller + banker := std.GetBanker(std.BankerTypeRealmSend) + send := std.Coins{{"ugnot", int64(amount)}} + banker.SendCoins(pkgaddr, caller, send) + wugnot.Burn(caller, amount) +} + +// render. +// + +func Render(path string) string { + parts := strings.Split(path, "/") + c := len(parts) + + switch { + case path == "": + return wugnot.RenderHome() + case c == 2 && parts[0] == "balance": + owner := std.Address(parts[1]) + balance, _ := wugnot.BalanceOf(owner) + return ufmt.Sprintf("%d\n", balance) + default: + return "404\n" + } +} + +// XXX: if we could call WUGNOT.XXX instead of XXX from gnokey, then, all the following lines would not be needed. + +// direct getters. +// XXX: remove them in favor of q_call wugnot.XXX + +func TotalSupply() uint64 { + return wugnot.TotalSupply() +} + +func BalanceOf(owner std.Address) uint64 { + balance, err := wugnot.BalanceOf(owner) + if err != nil { + panic(err) + } + return balance +} + +func Allowance(owner, spender std.Address) uint64 { + allowance, err := wugnot.Allowance(owner, spender) + if err != nil { + panic(err) + } + return allowance +} + +// setters. +// + +func Transfer(to std.Address, amount uint64) { + caller := std.PrevRealm().Addr() + err := wugnot.Transfer(caller, to, amount) + if err != nil { + panic(err) + } +} + +func Approve(spender std.Address, amount uint64) { + caller := std.PrevRealm().Addr() + err := wugnot.Approve(caller, spender, amount) + if err != nil { + panic(err) + } +} + +func TransferFrom(from, to std.Address, amount uint64) { + caller := std.PrevRealm().Addr() + err := wugnot.TransferFrom(caller, from, to, amount) + if err != nil { + panic(err) + } +} diff --git a/examples/gno.land/r/demo/wugnot/z0_filetest.gno b/examples/gno.land/r/demo/wugnot/z0_filetest.gno new file mode 100644 index 00000000000..fa2f45682b1 --- /dev/null +++ b/examples/gno.land/r/demo/wugnot/z0_filetest.gno @@ -0,0 +1,75 @@ +// PKGPATH: gno.land/r/demo/wugnot_test +package wugnot_test + +import ( + "fmt" + "std" + + "gno.land/p/demo/testutils" + "gno.land/r/demo/wugnot" +) + +var ( + addr1 = testutils.TestAddress("test1") + addrc = std.DerivePkgAddr("gno.land/r/demo/wugnot") + addrt = std.DerivePkgAddr("gno.land/r/demo/wugnot_test") +) + +func main() { + std.TestSetOrigPkgAddr(addrc) + std.TestIssueCoins(addrc, std.Coins{{"ugnot", 100000001}}) // TODO: remove this + + // issue ugnots + std.TestIssueCoins(addr1, std.Coins{{"ugnot", 100000001}}) + + // print initial state + printBalances() + // println(wugnot.Render("queues")) + // println("A -", wugnot.Render("")) + + std.TestSetOrigCaller(addr1) + std.TestSetOrigSend(std.Coins{{"ugnot", 123_400}}, nil) + wugnot.Deposit() + printBalances() + wugnot.Withdraw(4242) + printBalances() +} + +func printBalances() { + printSingleBalance := func(name string, addr std.Address) { + wugnotBal := wugnot.BalanceOf(addr) + std.TestSetOrigCaller(addr) + abanker := std.GetBanker(std.BankerTypeOrigSend) + acoins := abanker.GetCoins(addr).AmountOf("ugnot") + bbanker := std.GetBanker(std.BankerTypeRealmIssue) + bcoins := bbanker.GetCoins(addr).AmountOf("ugnot") + cbanker := std.GetBanker(std.BankerTypeRealmSend) + ccoins := cbanker.GetCoins(addr).AmountOf("ugnot") + dbanker := std.GetBanker(std.BankerTypeReadonly) + dcoins := dbanker.GetCoins(addr).AmountOf("ugnot") + fmt.Printf("| %-13s | addr=%s | wugnot=%-5d | ugnot=%-9d %-9d %-9d %-9d |\n", + name, addr, wugnotBal, acoins, bcoins, ccoins, dcoins) + } + println("-----------") + printSingleBalance("wugnot_test", addrt) + printSingleBalance("wugnot", addrc) + printSingleBalance("addr1", addr1) + println("-----------") +} + +// Output: +// ----------- +// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=0 | ugnot=200000000 200000000 200000000 200000000 | +// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 | +// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 | +// ----------- +// ----------- +// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=123400 | ugnot=200000000 200000000 200000000 200000000 | +// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 | +// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 | +// ----------- +// ----------- +// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=119158 | ugnot=200004242 200004242 200004242 200004242 | +// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=99995759 99995759 99995759 99995759 | +// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 | +// ----------- diff --git a/gno.land/cmd/gnoland/testdata/wugnot.txtar b/gno.land/cmd/gnoland/testdata/wugnot.txtar new file mode 100644 index 00000000000..5c2d7d3cb90 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/wugnot.txtar @@ -0,0 +1,43 @@ +gnoland start + +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +stdout '# wrapped GNOT \(\$wugnot\)' +stdout 'Decimals..: 0' +stdout 'Total supply..: 0' +stdout 'Known accounts..: 0' +stdout 'OK!' + +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Deposit -send 12345678ugnot -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout 'OK!' + +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +stdout 'Total supply..: 12345678' +stdout 'Known accounts..: 1' +stdout 'OK!' + +# XXX: use test2 instead (depends on https://github.com/gnolang/gno/issues/1269#issuecomment-1806386069) +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Deposit -send 12345678ugnot -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout 'OK!' + +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +stdout 'Total supply..: 24691356' +stdout 'Known accounts..: 1' # should be 2 once we can use test2 +stdout 'OK!' + +# XXX: replace hardcoded address with test3 +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Transfer -gas-fee 1000000ugnot -gas-wanted 2000000 -args 'g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq' -args '10000000' -broadcast -chainid=tendermint_test test1 +stdout 'OK!' + +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +stdout 'Total supply..: 24691356' +stdout 'Known accounts..: 2' # should be 3 once we can use test2 +stdout 'OK!' + +# XXX: use test3 instead (depends on https://github.com/gnolang/gno/issues/1269#issuecomment-1806386069) +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Withdraw -args 10000000 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout 'OK!' + +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +stdout 'Total supply..: 14691356' +stdout 'Known accounts..: 2' # should be 3 once we can use test2 +stdout 'OK!'