Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(examples): Ivan's registry, home realm #3354

Merged
merged 31 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
241eb1d
Created registry, home real in progress
Dec 17, 2024
452ced8
I have now added my home realm files, still need to add functionaliti…
Dec 18, 2024
0e75031
Merge branch 'master' of github.com:Ursulovic/gno into home-page
Dec 18, 2024
f81e4eb
Merge branch 'master' into home-page
Ursulovic Dec 19, 2024
65d4777
Finished all home realm functionalities, added tests aswell
Dec 19, 2024
5308289
Merge branch 'gnolang:master' into home-page
Ursulovic Dec 19, 2024
7e8de8c
Merge branch 'gnolang:master' into home-page
Ursulovic Dec 20, 2024
2f45a55
Minor updates to renderAboutMe function
Dec 20, 2024
7533f05
Merge branch 'gnolang:master' into home-page
Ursulovic Dec 20, 2024
b3ceda8
Fixed tests
Dec 20, 2024
92cfaea
Updated bio and fixed tests
Dec 20, 2024
1cf5070
Merge branch 'gnolang:master' into home-page
Ursulovic Dec 20, 2024
c907258
Merge branch 'gnolang:master' into home-page
Ursulovic Dec 23, 2024
2213227
Merge branch 'gnolang:master' into home-page
Ursulovic Jan 10, 2025
4e114b5
Created new home page, almost done
Jan 12, 2025
a122b2e
Finished home realm and tests
Jan 13, 2025
8805496
Merge branch 'gnolang:master' into home-page
Ursulovic Jan 13, 2025
4163ec7
Merge branch 'gnolang:master' into home-page
Ursulovic Jan 13, 2025
87c0f85
Almost implemented all suggestions
Jan 13, 2025
4f98afd
Home realm refactoring done
Jan 13, 2025
ec85925
Update home.gno
Ursulovic Jan 13, 2025
773ae0e
Merge branch 'gnolang:master' into home-page
Ursulovic Jan 14, 2025
706784e
Ran make fmt command in order to format all files
Jan 14, 2025
2808eaa
Merge branch 'master' into home-page
thehowl Jan 14, 2025
b610cd3
Merge branch 'gnolang:master' into home-page
Ursulovic Jan 14, 2025
1065ad2
I have removed initIsValidURL function and instead created new defaul…
Jan 14, 2025
5b182e8
I realised I have forgotten to make an url to connect studio dynamic,…
Jan 14, 2025
0bfa81e
I have now renamed owner variable to Ownable. Now it expored and Owna…
Jan 14, 2025
bb7676a
Renamed variable studioConnectUrl to connectUrl and function for upda…
Jan 14, 2025
f31ec47
Removed variable for url and update function for it and have set url …
Jan 14, 2025
c3b7f67
Ran fmt
Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/gno.land/r/ursulovic/home/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/r/ursulovic/home
160 changes: 160 additions & 0 deletions examples/gno.land/r/ursulovic/home/home.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package home

import (
"std"
"strconv"
"strings"

"gno.land/p/demo/ownable"
"gno.land/p/moul/md"
"gno.land/r/leon/hof"

"gno.land/r/ursulovic/registry"
)

var (
aboutMe string
selectedImage string
owner *ownable.Ownable

githubUrl string
linkedinUrl string
imageUpdatePrice int64

isValidURL func(string) bool
)

func init() {
owner = ownable.NewWithAddress(registry.MainAddress())
leohhhn marked this conversation as resolved.
Show resolved Hide resolved

aboutMe = "Hi, I'm Ivan Ursulovic, a computer engineering graduate, blockchain enthusiast, and backend developer specializing in ASP.NET. I love learning new things and taking on challenges."
selectedImage = "https://i.ibb.co/W28NPkw/beograd.webp"

githubUrl = "https://github.com/ursulovic"
linkedinUrl = "https://www.linkedin.com/in/ivan-ursulovic-953310190/"
imageUpdatePrice = 5000000
initIsValidURL()
hof.Register()
}

func Render(s string) string {
var sb strings.Builder
sb.WriteString(renderAboutMe())
sb.WriteString(renderSelectedImage())
sb.WriteString(renderContactsUrl())
return sb.String()
}

func initIsValidURL() {
isValidURL = func(url string) bool {
const urlPrefix string = "https://i.ibb.co/"

if !strings.HasPrefix(url, urlPrefix) {
return false
}

if !(strings.HasSuffix(url, ".jpg") ||
strings.HasSuffix(url, ".png") ||
strings.HasSuffix(url, ".gif") ||
strings.HasSuffix(url, ".webp")) {
return false
}

urlPath := strings.TrimPrefix(url, "https://i.ibb.co/")
parts := strings.Split(urlPath, "/")

if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
return false
}

return true
}
}
leohhhn marked this conversation as resolved.
Show resolved Hide resolved

func UpdateSelectedImage(url string) {
if !isValidURL(url) {
panic("Url is not valid!")
}

sentCoins := std.GetOrigSend()

if len(sentCoins) != 1 && sentCoins.AmountOf("ugnot") == imageUpdatePrice {
panic("Please send exactly " + strconv.Itoa(int(imageUpdatePrice)) + " ugnot")
}

selectedImage = url
}

func renderSelectedImage() string {
var sb strings.Builder

sb.WriteString(md.HorizontalRule())
sb.WriteString("\n")

sb.WriteString(md.H2("📸 Featured Image"))
sb.WriteString("\n")

sb.WriteString(md.Image("", selectedImage))
sb.WriteString("\n")

sb.WriteString(md.H4("✨ " + md.Link("Change this image for "+strconv.Itoa(int(imageUpdatePrice/1000000))+" GNOT. To update, set a direct image URL from ImgBB.", "https://www.google.com") + " ✨"))

return sb.String()
}

func renderAboutMe() string {
var sb strings.Builder

sb.WriteString(md.H1("👋 Welcome to Ivan's Homepage!"))
sb.WriteString("\n")

sb.WriteString(md.H2("👨‍💻 About Me"))
sb.WriteString("\n")

sb.WriteString(md.Blockquote(aboutMe))

return sb.String()
}

func renderContactsUrl() string {
var sb strings.Builder

sb.WriteString(md.HorizontalRule())
sb.WriteString("\n")

sb.WriteString(md.H2("🔗 Let's Connect"))
sb.WriteString("\n")

items := []string{
"🐙 " + md.Link("GitHub", githubUrl),
"💼 " + md.Link("LinkedIn", linkedinUrl),
}
sb.WriteString(md.BulletList(items))

return sb.String()
}

func UpdateGithubUrl(url string) {
owner.AssertCallerIsOwner()
githubUrl = url
}

func UpdateLinkedinUrl(url string) {
owner.AssertCallerIsOwner()
linkedinUrl = url
}

func UpdateAboutMe(text string) {
owner.AssertCallerIsOwner()
aboutMe = text
}

func UpdateImagePrice(newPrice int64) {
owner.AssertCallerIsOwner()
imageUpdatePrice = newPrice
}

func UpdateIsValidURLFunction(f func(string) bool) {
owner.AssertCallerIsOwner()
isValidURL = f
}
97 changes: 97 additions & 0 deletions examples/gno.land/r/ursulovic/home/home_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package home

import (
"std"
"testing"

"gno.land/p/demo/testutils"
)

func TestUpdateGithubUrl(t *testing.T) {
caller := std.Address("g1d24j8fwnc0w5q427fauyey4gdd30qgu69k6n0x")
std.TestSetOrigCaller(caller)

newUrl := "https://github.com/example"

UpdateGithubUrl(newUrl)

if githubUrl != newUrl {
t.Fatalf("GitHub url not updated properly!")
}
}

func TestUpdateLinkedinUrl(t *testing.T) {
caller := std.Address("g1d24j8fwnc0w5q427fauyey4gdd30qgu69k6n0x")
std.TestSetOrigCaller(caller)

newUrl := "https://www.linkedin.com/in/example"

UpdateGithubUrl(newUrl)

if githubUrl != newUrl {
t.Fatalf("LinkedIn url not updated properly!")
}
}

func TestUpdateAboutMe(t *testing.T) {
caller := std.Address("g1d24j8fwnc0w5q427fauyey4gdd30qgu69k6n0x")
std.TestSetOrigCaller(caller)

newAboutMe := "This is new description!"

UpdateAboutMe(newAboutMe)

if aboutMe != newAboutMe {
t.Fatalf("About mew not updated properly!")
}
}

func TestUpdateSelectedImage(t *testing.T) {
var user = testutils.TestAddress("user")
std.TestSetOrigCaller(user)

validImageUrl := "https://i.ibb.co/hLtmnX0/beautiful-rain-forest-ang-ka-nature-trail-doi-inthanon-national-park-thailand-36703721.webp"

coinsSent := std.NewCoins(std.NewCoin("ugnot", 5000000)) // Update to match the price expected by your function
std.TestSetOrigSend(coinsSent, std.NewCoins())

UpdateSelectedImage(validImageUrl)

if selectedImage != validImageUrl {
t.Fatalf("Valid image URL rejected!")
}

invalidImageUrl := "https://ibb.co/Kb3rQNn"

defer func() {
if r := recover(); r == nil {
t.Fatalf("Expected panic for invalid image URL, but got no panic")
}
}()

UpdateSelectedImage(invalidImageUrl)

invalidCoins := std.NewCoins(std.NewCoin("ugnot", 1000000))
std.TestSetOrigSend(invalidCoins, std.NewCoins())

defer func() {
if r := recover(); r == nil {
t.Fatalf("Expected panic for incorrect coin denomination or amount, but got no panic")
}
}()

UpdateSelectedImage(validImageUrl)
}

func TestUpdateImagePrice(t *testing.T) {
caller := std.Address("g1d24j8fwnc0w5q427fauyey4gdd30qgu69k6n0x")
std.TestSetOrigCaller(caller)

var newImageUpdatePrice int64 = 3000000

UpdateImagePrice(newImageUpdatePrice)

if imageUpdatePrice != newImageUpdatePrice {
t.Fatalf("Image update price not updated properly!")
}
}
1 change: 1 addition & 0 deletions examples/gno.land/r/ursulovic/registry/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/r/ursulovic/registry
59 changes: 59 additions & 0 deletions examples/gno.land/r/ursulovic/registry/registry.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package registry

import (
"errors"
"std"
)

var (
mainAddress std.Address
backupAddress std.Address

ErrInvalidAddr = errors.New("Ivan's registry: Invalid address")
ErrUnauthorized = errors.New("Ivan's registry: Unauthorized")
)

func init() {
mainAddress = "g1d24j8fwnc0w5q427fauyey4gdd30qgu69k6n0x"
backupAddress = "g1mw2xft3eava9kfhqw3fjj3kkf3pkammty0mtv7"
}

func MainAddress() std.Address {
return mainAddress
}

func BackupAddress() std.Address {
return backupAddress
}

func SetMainAddress(addr std.Address) error {
assertAuthorized()

if !addr.IsValid() {
return ErrInvalidAddr
}

mainAddress = addr
return nil
}

func SetBackupAddress(addr std.Address) error {
assertAuthorized()

if !addr.IsValid() {
return ErrInvalidAddr
}

backupAddress = addr
return nil
}

// It will stay here for now, might be useful later
func assertAuthorized() {
Ursulovic marked this conversation as resolved.
Show resolved Hide resolved
caller := std.PrevRealm().Addr()
isAuthorized := caller == mainAddress || caller == backupAddress

if !isAuthorized {
panic(ErrUnauthorized)
}
}
Loading