diff --git a/.gitignore b/.gitignore index a23836a..3adb90a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ # generated files from reveal tool slides.html + +presentations/static/ +presentations/templates \ No newline at end of file diff --git a/README.md b/README.md index 99a3c4f..7fe484c 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,12 @@ presentations. |Date |Title |Speakers |Presentation |Recording | |---- |----- |-------- |------------ |--------- | +|2025.01.09 |Designing Seamless Interconnected dApps with Gno |[@moul](https://github.com/moul) |[Slides](https://gnolang.github.io/workshops/presentations/2025-01-09--buidleu--manfred/presentation.slide.html#1) |--- | |2024.09.23 |Distributed Communities - How to build timeless and decentralized apps, with Go |[@thehowl](https://github.com/thehowl) |[Slides](https://gnolang.github.io/workshops/presentations/2024-09-23--distributed-communities--morgan/slides.html) |[Video](https://www.youtube.com/watch?v=b3zRbVcJxyE) | |2024.08.20 |A gentle intro to gno.land |[@leohhhn](https://github.com/leohhhn) |[Slides](presentations/2024-08-20--gentle-intro-to-gnoland--leon/presentation.pdf) |[Video](https://www.youtube.com/watch?v=hTGeG0z09NU) | |2024.08.05 |Intro to gno.land |[@leohhhn](https://github.com/leohhhn) |[Slides](https://docs.google.com/presentation/d/1tnplCWxhg-RFatDS3w1iJnO0vSfBAuw2ZA0ommNJQOU/edit?usp=sharing) |--- | -|2024.07.13 |Building with Gno.land: A Practical Workshop on Smart Contracts |[@gfanton](https://github.com/gfanton) |[Slides](presentations/2024-07-13--nebular--gfanton/README.md) |[Video](https://www.youtube.com/watch?v=oBQ-t_E0QpI) | |2024.07.13 |Gno: Examples and Comparisons |[@moul](https://github.com/moul) |[Slides](https://gnolang.github.io/workshops/presentations/2024-07-13--nebular--manfred/presentation.slide.html#1) |[Video](https://www.youtube.com/watch?v=Zsl3xu_Edcc) | +|2024.07.13 |Building with Gno.land: A Practical Workshop on Smart Contracts |[@gfanton](https://github.com/gfanton) |[Slides](presentations/2024-07-13--nebular--gfanton/README.md) |[Video](https://www.youtube.com/watch?v=oBQ-t_E0QpI) | |2024.07.09 |Building a Deterministic Interpreter in Go: Readability vs Performance |[@jaekwon](https://github.com/jaekwon) |[Slides](presentations/2024-07-09--gophercon-us--jae) |[Video](https://www.youtube.com/watch?v=betUkghf_jo) | |2024.07.08 |Building a Decentralized App on gno.land |[@deelawn](https://github.com/deelawn) |[Slides](presentations/2024-07-08--gophercon-us--dylan) |[Video](https://www.youtube.com/watch?v=lwL2VyjaV-A) | |2024.06.17 |Envisioning a Go-Powered Ecosystem: The Ultimate Go Computer |[@moul](https://github.com/moul) |[Slides](presentations/2024-06-17--gophercon-berlin--manfred) |[Video](https://youtu.be/dLE2-8QPK64?si=IidxNLGrwwS6jbYL) | @@ -42,6 +43,10 @@ presentations. |2022.09.29 |Intro to Gno |[@moul](https://github.com/moul), [@pwnh4](https://github.com/pwnh4) |[Slides](https://github.com/xplrz/gnoland-workshop) |--- | |2022.09.13 |Intro to the Gno Smart Contract Platform and Blockchain |[@moul](https://github.com/moul) |[Slides](presentations/2022-09-13--berlin--manfred/slides.pdf) |[Video](https://www.youtube.com/watch?v=S36kA5RqLvs) | + + + + _This table is autogenerated based on the [./presentations](./presentations) folder._ ## Resources diff --git a/go.mod b/go.mod index c904e7d..9b53a59 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,9 @@ toolchain go1.22.3 require ( github.com/campoy/embedmd v1.0.0 - github.com/gnolang/gno v0.2.0 + github.com/gnolang/gno v0.0.0-20250109171001-b60f86478da2 github.com/soypat/go-presentx v1.1.0 - golang.org/x/tools v0.23.0 + golang.org/x/tools v0.24.0 gopkg.in/yaml.v3 v3.0.1 moul.io/mdtable v1.0.0 ) @@ -17,10 +17,10 @@ require ( github.com/peterbourgon/ff/v3 v3.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/soypat/rebed v0.2.2 // indirect - github.com/yuin/goldmark v1.4.13 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect + github.com/yuin/goldmark v1.7.2 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect moul.io/banner v1.0.1 // indirect moul.io/climan v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index 604f6a8..6a5341b 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gnolang/gno v0.2.0 h1:s33kyRByweDxxHMZMQKJtCDQpueTCYCFBqlLHwr6P+Y= -github.com/gnolang/gno v0.2.0/go.mod h1:dBaL1Au2MNLol+3FXdCv+IKLJnMKtTmIt778zsKjVu0= +github.com/gnolang/gno v0.0.0-20250109171001-b60f86478da2 h1:NSdDGlVJtDDrocvtIQ9/1CN1NpeTfcqTTTd3lvB429s= +github.com/gnolang/gno v0.0.0-20250109171001-b60f86478da2/go.mod h1:60XncI6LLLwujdl/jAX5APhSf5t3pn+PTVdK2vmbYJE= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -34,8 +34,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.2 h1:NjGd7lO7zrUn/A7eKwn5PEOt4ONYGqpxSEeZuduvgxc= +github.com/yuin/goldmark v1.7.2/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= @@ -51,8 +51,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -60,10 +60,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -71,8 +71,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20201109182053-3db8fd265862/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/presentations/2025-01-09--buidleu--manfred/Makefile b/presentations/2025-01-09--buidleu--manfred/Makefile new file mode 100644 index 0000000..842599e --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/Makefile @@ -0,0 +1,5 @@ +run: + cd ..; go run golang.org/x/tools/cmd/present -http 0.0.0.0:3999 # -base ../.. + +runx: + cd ..; go run github.com/soypat/go-presentx -http 0.0.0.0:3999 diff --git a/presentations/2025-01-09--buidleu--manfred/code/.gitignore b/presentations/2025-01-09--buidleu--manfred/code/.gitignore new file mode 100644 index 0000000..e33609d --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/.gitignore @@ -0,0 +1 @@ +*.png diff --git a/presentations/2025-01-09--buidleu--manfred/code/buidl20.gno b/presentations/2025-01-09--buidleu--manfred/code/buidl20.gno new file mode 100644 index 0000000..b032b85 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/buidl20.gno @@ -0,0 +1,21 @@ +// https://gno.land/r/moul/x/buidl20$source +package buidl20 + +import ( + "std" + "gno.land/p/demo/grc/grc20" +) + +// Token: public safe object for composability +// adm: privileged object for minting +var Token, adm = grc20.NewToken("Buidl", "BDL", 4) + +// grc20 API for the caller +var UserTeller = Token.CallerTeller() + +func init() { + adm.Mint(1_000_000, std.GetOrigCaller()) // mint 1M to the contract deployer. +} + +// optional helpers +// [...] diff --git a/presentations/2025-01-09--buidleu--manfred/code/counter.gno b/presentations/2025-01-09--buidleu--manfred/code/counter.gno new file mode 100644 index 0000000..74b111e --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/counter.gno @@ -0,0 +1,11 @@ +package counter + +var Counter int + +func Inc() { + Counter += 1 +} + +func Render(path string) string { + return "My Super Counter: " + Counter +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/counter_2.gno b/presentations/2025-01-09--buidleu--manfred/code/counter_2.gno new file mode 100644 index 0000000..2154c7d --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/counter_2.gno @@ -0,0 +1,22 @@ +package counter + +import "std" + +var ( + Counter int + LastCaller std.Address +) + +func Inc() int { + return addToCounter(1) +} + +func Add(amount int) int { + return addToCounter(amount) +} + +func addToCounter(amount int) int { + Counter += amount + LastCaller = std.GetOrigCaller() + return Counter +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/dao_aggregated.gno b/presentations/2025-01-09--buidleu--manfred/code/dao_aggregated.gno new file mode 100644 index 0000000..83588c5 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/dao_aggregated.gno @@ -0,0 +1,23 @@ +package aggregateddao + +import "gno.land/p/dao" + +type AggregatedDAO struct { dao1, dao2 dao.DAO } + +func (a *AggregatedDAO) Propose(def dao.PropDefinition) (dao.Proposal, error) { + prop1, _ := a.dao1.Propose(def) + prop2, _ := a.dao2.Propose(def) + // [...] +} + +func (a *AggregatedDAO) Len() int { return a.dao1.Len() + a.dao2.Len() } + +func (a *AggregatedDAO) ActiveProposals() dao.PropList { + return append(a.dao1.ActiveProposals(), a.dao2.ActiveProposals()...) +} + +func (a *AggregatedDAO) ArchivedProposals() dao.PropList { + return append(a.dao1.ArchivedProposals(), a.dao2.ArchivedProposals()...) +} + +// [...] diff --git a/presentations/2025-01-09--buidleu--manfred/code/dao_composition.gno b/presentations/2025-01-09--buidleu--manfred/code/dao_composition.gno new file mode 100644 index 0000000..5434e44 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/dao_composition.gno @@ -0,0 +1,10 @@ +// gno.land/r/foobardao +package foobardao + +import ( + "gno.land/r/foodao" + "gno.land/r/bardao" + "gno.land/p/aggregateddao" +) + +var FooBarDAO = aggregateddao.New(foodao.DAO, bardao.DAO) diff --git a/presentations/2025-01-09--buidleu--manfred/code/dao_impl.gno b/presentations/2025-01-09--buidleu--manfred/code/dao_impl.gno new file mode 100644 index 0000000..9e694aa --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/dao_impl.gno @@ -0,0 +1,13 @@ +package foodao + +import "gno.land/p/dao" // interface + +// FooDAO implements the dao.DAO interface. +type FooDAO struct { proposals []dao.Proposal, voters []std.Address } + +func (d *FooDAO) Propose(def PropDefinition) (Proposal, error) { /* [...] */ } +func (d *FooDAO) GetProposal(proposalID uint64) (Proposal, error) { /* [...] */ } +func (d *FooDAO) Execute(proposalID uint64) error { /* [...] */ } +func (d *FooDAO) ActiveProposals() PropList { /* [...] */ } +func (d *FooDAO) ArchivedProposals() PropList { /* [...] */ } +func (d *FooDAO) Len() int { /* [...] */ } diff --git a/presentations/2025-01-09--buidleu--manfred/code/dao_type.gno b/presentations/2025-01-09--buidleu--manfred/code/dao_type.gno new file mode 100644 index 0000000..4cc16a9 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/dao_type.gno @@ -0,0 +1,14 @@ +// gno.land/p/dao +package dao + +type DAO interface { + // Core proposal operations + Propose(def PropDefinition) (Proposal, error) + GetProposal(proposalID uint64) (Proposal, error) + Execute(proposalID uint64) error + + // List operations + ActiveProposals() PropList + ArchivedProposals() PropList + Len() int +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/executable_proposal.gno b/presentations/2025-01-09--buidleu--manfred/code/executable_proposal.gno new file mode 100644 index 0000000..8cd9b29 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/executable_proposal.gno @@ -0,0 +1,23 @@ +// prop1.gno + +import "gno.land/r/gov/dao" +import "gno.land/r/buidl/buidl20" + +func init() { + closure := func() error { + // this closure will preserve the execution context at the time of + // creation, even if the proposal is executed by someone else. + return executor() + } + prop := dao.ProposalRequest{ + Title: "", + Description: "lorem ipsum dolor sit amet", + Executor: closure, + } + dao.Propose(prop) +} + +func executor() error { + buidl20.TransferTo("g12345678", 1_000_000) // transfer 1M $BUIDL + return nil +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/grc20_type.gno b/presentations/2025-01-09--buidleu--manfred/code/grc20_type.gno new file mode 100644 index 0000000..a98ad71 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/grc20_type.gno @@ -0,0 +1,23 @@ +package grc20 // gno.land/p/demo/grc/grc20 + +type Teller interface { + TotalSupply() uint64 + BalanceOf(account std.Address) uint64 + Transfer(to std.Address, amount uint64) error + Allowance(owner, spender std.Address) uint64 + Approve(spender std.Address, amount uint64) error + TransferFrom(from, to std.Address, amount uint64) error +} + +type Token struct { + name, symbol string + decimals uint + ledger *PrivateLedger +} + +type PrivateLedger struct { + totalSupply uint64 + balances, allowances avl.Tree +} + +func NewToken(name, symbol string, decs uint) (*Token, *PrivateLedger) { /*...*/ } diff --git a/presentations/2025-01-09--buidleu--manfred/code/grc20factory.gno b/presentations/2025-01-09--buidleu--manfred/code/grc20factory.gno new file mode 100644 index 0000000..f3a36b1 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/grc20factory.gno @@ -0,0 +1,23 @@ +// gno.land/r/demo/grc20factory +package grc20factory + +var instances avl.Tree // symbol -> instance + +type instance struct { + token *grc20.Token + ledger *grc20.PrivateLedger + admin *ownable.Ownable + faucet uint64 // per-request amount. disabled if 0. +} + +func New(name, symbol string, decimals uint, initialMint, faucet uint64) { + caller := std.PrevRealm().Addr() + token, ledger := grc20.NewToken(name, symbol, decimals) + if initialMint > 0 { + ledger.Mint(admin, initialMint) + } + owner := ownable.NewWithAddress(admin) + inst := instance{token: token, ledger: ledger, admin: owner, faucet: faucet} + instances.Set(symbol, &inst) + grc20reg.Register(token.Getter(), symbol) +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/grc20reg.gno b/presentations/2025-01-09--buidleu--manfred/code/grc20reg.gno new file mode 100644 index 0000000..0ba44e1 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/grc20reg.gno @@ -0,0 +1,14 @@ +// gno.land/r/demo/grc20reg +package grc20reg + +var registry = avl.NewTree() // rlmPath -> TokenGetter + +func Register(tokenGetter grc20.TokenGetter) { + rlmPath := std.PrevRealm().PkgPath() + registry.Set(rlmPath, tokenGetter) +} + +func Get(key string) grc20.TokenGetter { + tokenGetter, _ := registry.Get(key) + return tokenGetter +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/guest_book.gno b/presentations/2025-01-09--buidleu--manfred/code/guest_book.gno new file mode 100644 index 0000000..dde4e93 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/guest_book.gno @@ -0,0 +1,21 @@ +package guest + +import "std" + +var messages avl.Tree // std.Address -> string (message) + +func AddMessage(message string) { + caller := std.GetOrigCaller() + if _, ok := messages.Get(caller); ok { + panic("this user already post a message") + } + messages.Set(caller, message) // add message to our messages list +} + +func Render(path string) string { + var view string + for _, message := range messages { + view = view + "\n" + message // add message to the render + } + return view +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/hello.go b/presentations/2025-01-09--buidleu--manfred/code/hello.go new file mode 100644 index 0000000..6ebbec9 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/hello.go @@ -0,0 +1,5 @@ +package main + +func main() { + println("Hello, BUIDL! It's Manfred.") +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/hello_world.gno b/presentations/2025-01-09--buidleu--manfred/code/hello_world.gno new file mode 100644 index 0000000..044709e --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/hello_world.gno @@ -0,0 +1,5 @@ +package hello + +func Hello() string { + return "hello world" +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/interop.gno b/presentations/2025-01-09--buidleu--manfred/code/interop.gno new file mode 100644 index 0000000..34d4512 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/interop.gno @@ -0,0 +1,11 @@ +package alice + +var x int + +func GetX() int { + return x +} + +func SetX(n int) { + x = n +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/interop2.gno b/presentations/2025-01-09--buidleu--manfred/code/interop2.gno new file mode 100644 index 0000000..861dd97 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/interop2.gno @@ -0,0 +1,8 @@ +package bob + +import "alice" + +func IncrAlice() { + x := alice.GetX() + alice.SetX(x + 1) +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/minidex.gno b/presentations/2025-01-09--buidleu--manfred/code/minidex.gno new file mode 100644 index 0000000..3675d03 --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/minidex.gno @@ -0,0 +1,23 @@ +package dex + +func (dex *DEX) PlaceOrder(tokenFrom, tokenTo grc20.Token, amount uint64, isBuy bool) int { + trader, contract := std.PrevRealm().Addr(), std.CurrentRealm().Addr() + userBanker := grc20.AccountBanker(tokenFrom, "") + + allowance := userBanker.Allowance(trader, contract) + require(allowance >= amount, "insufficient allowance") + err := userBanker.TransferFrom(trader, contract, amount) + checkErr(err, "cannot retrieve tokens from allowance") + + order := &Order{trader: trader, tokenFrom: tokenFrom, tokenTo: tokenTo, amount: amount, isBuy: isBuy} + dex.Append(order) + std.Emit( + "order_placed", + "trader", trader.String(), + "tokenFrom", tokenFrom.GetName(), + "tokenTo", tokenTo.GetName(), + "amount", ufmt.Sprintf("%d", amount), + ) + + return dex.matchPairOrders(tokenFrom, tokenTo) +} diff --git a/presentations/2025-01-09--buidleu--manfred/code/solidity_721.sol b/presentations/2025-01-09--buidleu--manfred/code/solidity_721.sol new file mode 100644 index 0000000..a556e5d --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/code/solidity_721.sol @@ -0,0 +1,15 @@ +// Solidity example for ERC721Receiver check +interface IERC721Receiver { + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external returns (bytes4); +} + +// Solidity relies on checking bytes4 signature +require( + contract.onERC721Received.selector == bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")), + "Invalid ERC721 receiver" +); diff --git a/presentations/2025-01-09--buidleu--manfred/metadata.yml b/presentations/2025-01-09--buidleu--manfred/metadata.yml new file mode 100644 index 0000000..df9bf4d --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/metadata.yml @@ -0,0 +1,15 @@ +# Date of the workshop +date: "2025-01-09" +# Title of the workshop +title: "Designing Seamless Interconnected dApps with Gno" +# GitHub usernames of the speakers +speakers: + - "moul" +# Location of the workshop +location: "Lisbon, Portugal" +# At which event the workshop took place, if any +event: "BUIDL Europe 2025" +# Workshop slides link. If the link is local, only put the file name, without any other path parts. +slides: "https://gnolang.github.io/workshops/presentations/2025-01-09--buidleu--manfred/presentation.slide.html#1" +# Workshop recording +#recording: "" \ No newline at end of file diff --git a/presentations/2025-01-09--buidleu--manfred/presentation.slide b/presentations/2025-01-09--buidleu--manfred/presentation.slide new file mode 100644 index 0000000..4fc163c --- /dev/null +++ b/presentations/2025-01-09--buidleu--manfred/presentation.slide @@ -0,0 +1,166 @@ +# designing seamless interconnected dApps with gno +BUIDL Europe, 9 Jan 2025, Lisbon +Tags: golang, gnolang +Summary: TODO + +Manfred Touron +VP Eng., gno.land +https://gno.land/ +https://github.com/gnolang +@moul + +## bonjour, BUIDL! + +.code ./code/hello.go + +- Manfred Touron +- started with code, stuck with Go +- built Scaleway, Berty, and now gno.land + +## introduction + +- dapps are the future of web3 +- challenges: lack of modularity and composability, limited interoperability, siloed ecosystems +- goal: showcase gno's unique capabilities for building next-gen interconnected dapps + +## what is gno? + +- gno: transactional vm + - determinism: guaranteed + - state persistence: built-in + - sandboxed execution: safe and secure + - more info: https://docs.gno.land/reference/go-gno-compatibility +- gno.land: blockchain designed for modular, transparent, interoperable dapps + - proof of ...: new consensus mechanism + - tendermint2, ibcx, icsx + - hub of the gno ecosystem + +## gno hello world + +.code ./code/hello_world.gno + +## counter.gno - persistency and Render() + +.code ./code/counter.gno + +## counter.gno - private helpers + +.code ./code/counter_2.gno + +## guestbook.gno + +.code ./code/guest_book.gno + +## why gno? + +the gnovm enables: + +seamless interoperability of + +untrusted user programs + +written in a good language + +## alice.gno, bob.gno + +.code ./code/interop.gno + +.code ./code/interop2.gno + +## packages and realms + +- packages + - reusable code modules + - pure: stateless, cannot import realms +- realms + - end-user smart contracts with persistent state via global variables + - exported functions accessible through rpc + - supports contract-to-contract interactions + +## gno grc20 package + +.code ./code/grc20_type.gno + +## gno buidl20 realm + +.code ./code/buidl20.gno + +## gno safe objects + +- gno objects can act like mini-dApps with secure boundaries +- factory contracts can create independent objects accessible to other contracts + +## gno grc20reg realm + +.code ./code/grc20reg.gno + +## gno grc20factory realm + +.code ./code/grc20factory.gno + +## gno full type safety + +- how gno avoids Solidity's pitfalls (e.g., unsafe casting, complicated Yul interactions) +- contracts are imported directly, exposing clean interfaces like GRC20 +- eliminates casting addresses to contracts for safer development + +.code ./code/solidity_721.sol + +## gno minidex + +.code ./code/minidex.gno + +## gno pausable closures + +- closures instanciated during transactions can pause and resume seamlessly +- preserve state and ownership for asynchronous execution +- allows arbitrary code execution for governance proposals + +## gno govdao proposal + +.code ./code/executable_proposal.gno + +## gno composition + +- similar to Go composition +- can compose package logic, or realms with state + +## a gno DAO interface + +.code ./code/dao_type.gno + +## a gno DAO implementation + +.code ./code/dao_impl.gno + +## a gno DAO aggregator + +.code ./code/dao_aggregated.gno + +## a gno DAO composition + +.code ./code/dao_composition.gno + +## DAO compositions ideas + +- sum: combine daos by aggregating proposals and votes +- weighted: assign different voting weights to daos +- delayed: wrap daos to enforce delays before actions +- fallback: use secondary dao if primary lacks data +- sharded: partition proposals into different daos +- proxy: forward actions to another dao without exposure +- crosschain: aggregate daos across different blockchains +- dynamic: switch daos based on external conditions +- routing: pass specific proposals to certain daos +- hybrid: mix centralized and decentralized governance +- ... + +## road ahead + +- gno is designed for next-gen modular, interoperable dapps +- launching soon as experimental chain +- opportunities for developers to contribute and innovate +- join the community and start building today +- -> https://gno.land + +thank you! \ No newline at end of file diff --git a/scripts/lint.go b/scripts/lint.go index 353eff4..24a80fa 100644 --- a/scripts/lint.go +++ b/scripts/lint.go @@ -32,6 +32,11 @@ func execLint(cfg *cfg) error { var dates []string for _, dir := range dirs { + // Skip special dirs + switch dir.Name() { + case "static", "templates": + continue + } // Skip non-dirs if !dir.IsDir() { continue @@ -51,8 +56,9 @@ func execLint(cfg *cfg) error { cts := string(rawContents) for _, date := range dates { + date = strings.ReplaceAll(date, "-", ".") if !strings.Contains(cts, date) { - panic("could not find some items in README table - did you run `make build`?") + panic("could not find some items in README table - did you run `make build`? (" + date + ")") } }