-
Notifications
You must be signed in to change notification settings - Fork 389
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): Gnofundme #2085
Open
MalekLahbib
wants to merge
76
commits into
gnolang:master
Choose a base branch
from
MalekLahbib:gnofundme
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 75 commits
Commits
Show all changes
76 commits
Select commit
Hold shift + click to select a range
bfce4e9
added todolist pckg and realm
MalekLahbib 49af024
feat: Added todolist pkg and realm
MalekLahbib 5896691
feat: Added todolist pkg and realm
MalekLahbib 049a77c
feat: Added todolist pkg and realm
MalekLahbib f4953ee
Merge branch 'gnolang:master' into master
MalekLahbib 914493d
Merge branch 'gnolang:master' into master
MalekLahbib ec3f07d
Merge branch 'gnolang:master' into master
MalekLahbib f0cdb06
feat(examples): add todolist package & realm
MalekLahbib 78a6e7a
Merge branch 'master' of github.com:MalekLahbib/gno
MalekLahbib a48d20f
feat(examples): add todolist package & realm
MalekLahbib 455d189
Merge branch 'gnolang:master' into master
MalekLahbib a1435e0
modified realm pkg name and todolist realm testfile
MalekLahbib 44b2532
Merge branch 'gnolang:master' into master
MalekLahbib f0ee455
Merge remote-tracking branch 'upstream/master'
MalekLahbib 9d2cce0
Merge branch 'master' of github.com:MalekLahbib/gno
MalekLahbib 511901a
Merge branch 'gnolang:master' into master
MalekLahbib 1031545
Merge branch 'master' of github.com:MalekLahbib/gno
MalekLahbib 1963b82
Merge branch 'gnolang:master' into master
MalekLahbib 92b5b1c
Merge branch 'master' of github.com:MalekLahbib/gno
MalekLahbib 961593b
Merge branch 'gnolang:master' into master
MalekLahbib 95365a7
Merge branch 'master' of github.com:MalekLahbib/gno
MalekLahbib 1a780ec
gnofundme 1st step
MalekLahbib 0596ca0
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 2e9c087
added user getters and test file
MalekLahbib 0ca4ea1
separated user struct and getters in file users.gno and added campaig…
MalekLahbib 7cbed2e
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 3aa153d
Merge branch 'gnolang:master' into gnofundme
MalekLahbib cfdce6f
TestAddContributor
MalekLahbib 37e782e
added realm v1
MalekLahbib 3d89b2d
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 3b96f92
some tests
MalekLahbib ebf3731
realm v1
MalekLahbib 137c510
realm display changes: displaying a clickable link for campaigns
MalekLahbib 1ba03ce
contributor.gno + clickable campaigns link
MalekLahbib 4fd1552
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 6168353
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 73dbde8
Merge branch 'gnolang:master' into gnofundme
MalekLahbib d872154
Merge branch 'gnolang:master' into gnofundme
MalekLahbib c719fd6
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 89c6f82
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 286632f
Merge branch 'gnolang:master' into gnofundme
MalekLahbib a4ed2d4
added gnofundme to examples, not finished yet, to open a PR and a dis…
MalekLahbib 90ec356
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 9b85ef7
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 3327678
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 3e20ebc
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 6662611
new updates
MalekLahbib 1505d3e
16-09
MalekLahbib 5e2ac24
some modifs + withdraw function but still time.now() doesnt seem to w…
MalekLahbib 9103465
withdraw test // difficulties to understand TestSetOrigSend and other…
MalekLahbib 07c51b1
chore: add dummy filetest examples
moul 5c6f1dc
...
MalekLahbib 5ac1e45
Merge branch 'gnolang:master' into gnofundme
MalekLahbib c9e0e44
used iota
MalekLahbib dd9e20f
delete comments on campaign struct
MalekLahbib 9c48fb4
somde modifs + deleted escape string func
MalekLahbib 3d2daf2
changed package name in the realm
MalekLahbib dfc6988
added render func to the package
MalekLahbib a6b2949
gno mod tidy
MalekLahbib 49c94c2
changed some vars to const in gnofundme_test.gno
MalekLahbib 711db8e
deleted NewUser func, will use ../demo/users
MalekLahbib 27acf91
'some modifs, 1st test with json pkg'
MalekLahbib 178b177
Merge branch 'gnolang:master' into gnofundme
MalekLahbib 2b42657
gno mod
MalekLahbib 5093d30
deleted non useful \n in p/gnofundme.gno, used uassert in contributor…
MalekLahbib b62cdcb
used json package in p/gnofundme
MalekLahbib ee4e630
changed some vars to uint64, used uassert for test
MalekLahbib 48a436b
some minors modifs to realm
MalekLahbib 4b765d9
realm and realm test modifs
MalekLahbib 53cebb6
package test modifs
MalekLahbib 587b6dc
gno mod tidy
MalekLahbib 410eb71
1 modif
MalekLahbib 2e9e633
Merge branch 'gnolang:master' into gnofundme
MalekLahbib c06366f
Merge branch 'gnolang:master' into gnofundme
MalekLahbib c2cf535
folders under namespace
MalekLahbib 2503e34
Merge branch 'gnolang:master' into gnofundme
MalekLahbib File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package gnofundme | ||
|
||
import ( | ||
"time" | ||
|
||
"gno.land/p/demo/json" | ||
"gno.land/p/demo/ufmt" | ||
pusers "gno.land/p/demo/users" | ||
) | ||
|
||
type Contributor struct { | ||
// the user who contributed | ||
user *pusers.User | ||
// the date of the contribution | ||
Date time.Time | ||
// the amount of the contribution | ||
Amount uint64 | ||
// whether the contributor wants to be displayed (Anonymous in case of false) | ||
display bool | ||
} | ||
|
||
func NewContributor(user *pusers.User, date time.Time, amount uint64, display bool) *Contributor { | ||
return &Contributor{ | ||
user: user, | ||
Date: date, | ||
Amount: amount, | ||
display: display, | ||
} | ||
} | ||
|
||
func (c Contributor) GetUser() *pusers.User { | ||
return c.user | ||
} | ||
|
||
func (c Contributor) GetDisplay() bool { | ||
return c.display | ||
} | ||
|
||
func (c Contributor) String() string { | ||
node := json.ObjectNode("Contributor", map[string]*json.Node{ | ||
"Address": json.StringNode("Address", c.user.Address.String()), | ||
"date": json.StringNode("date", c.Date.Format(time.RFC822)), | ||
"amount": json.NumberNode("amount", float64(c.Amount)), | ||
"display": json.StringNode("display", FormatBool(c.display)), | ||
}) | ||
value, err := json.Marshal(node) | ||
if err != nil { | ||
panic(ufmt.Sprintf("unexpected error: %s", err)) | ||
} | ||
|
||
return string(value) | ||
} | ||
|
||
func FormatBool(b bool) string { | ||
if b { | ||
return "true" | ||
} | ||
return "false" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package gnofundme | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"gno.land/p/demo/uassert" | ||
"gno.land/r/demo/users" | ||
) | ||
|
||
func TestNewContributor(t *testing.T) { | ||
user := users.GetUserByName("demo") | ||
amount := uint64(500) | ||
display := true | ||
date := time.Unix(time.Now().Unix(), 0) | ||
contributor := NewContributor(user, date, amount, display) | ||
|
||
uassert.Equal(t, contributor.GetUser().Address, user.Address) | ||
|
||
uassert.False(t, contributor.Date.IsZero()) | ||
|
||
uassert.Equal(t, contributor.Amount, amount) | ||
|
||
uassert.Equal(t, contributor.GetDisplay(), display) | ||
Comment on lines
+18
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for these newlines |
||
|
||
json := `{"Address":"g13ek2zz9qurzynzvssyc4sthwppnruhnp0gdz8n","date":"13 Feb 09 23:31 UTC","amount":500,"display":"true"}` | ||
|
||
uassert.Equal(t, contributor.String(), json) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module gno.land/p/malek_/gnofundme | ||
|
||
require ( | ||
gno.land/p/demo/json v0.0.0-latest | ||
gno.land/p/demo/testutils v0.0.0-latest | ||
gno.land/p/demo/uassert v0.0.0-latest | ||
gno.land/p/demo/ufmt v0.0.0-latest | ||
gno.land/p/demo/users v0.0.0-latest | ||
gno.land/r/demo/users v0.0.0-latest | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package gnofundme // Package gnofundme provides a simple crowdfunding system. | ||
|
||
import ( | ||
"bytes" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"gno.land/p/demo/json" | ||
"gno.land/p/demo/ufmt" | ||
pusers "gno.land/p/demo/users" | ||
) | ||
|
||
type ctype int | ||
|
||
const ( | ||
Personal ctype = iota | ||
// for a person (yourself or another person): can be for humanitarian reason, emergency needs, or other (beneficiary = owner) | ||
Cause | ||
// for a cause: you will manage the funds (based on trust) (beneficiary = owner) | ||
Organism | ||
// for an organism, charity... (beneficiary != owner) | ||
// the next types are for companies(startup projects...) crowdfunding | ||
Donation | ||
Reward | ||
Equity | ||
) | ||
|
||
func (c ctype) String() string { | ||
return [...]string{"Personal", "Cause", "Organism", "Donation", "Reward", "Equity"}[c] | ||
} | ||
|
||
type Campaign struct { | ||
// Campaign type | ||
Ctype ctype | ||
Title string | ||
Description string | ||
Goal uint64 | ||
Current uint64 | ||
Begin time.Time | ||
Deadline time.Time | ||
Owner *pusers.User | ||
// Campaign beneficiary (can be the owner or another address) | ||
Beneficiary *pusers.User | ||
contributors []*Contributor | ||
} | ||
|
||
func NewCampaign(ct int, title string, description string, goal uint64, begin time.Time, deadline time.Time, owner *pusers.User, beneficiary *pusers.User) *Campaign { | ||
campaign := &Campaign{ | ||
Ctype: ctype(ct), | ||
Title: title, | ||
Description: description, | ||
Goal: goal, | ||
Current: 0, | ||
Begin: begin, | ||
Deadline: deadline, | ||
Owner: owner, | ||
Beneficiary: beneficiary, | ||
contributors: make([]*Contributor, 0), | ||
} | ||
|
||
return campaign | ||
} | ||
|
||
func (c Campaign) GetContributors() []*Contributor { | ||
return c.contributors | ||
} | ||
|
||
func (c *Campaign) AddContributor(user *pusers.User, date time.Time, amount uint64, display bool) *Contributor { | ||
c.Current += amount | ||
contributor := NewContributor(user, date, amount, display) | ||
c.contributors = append(c.contributors, contributor) | ||
|
||
return contributor | ||
} | ||
|
||
// CampaignsToJSONString converts a slice of Campaigns structs into a JSON string | ||
func CampaignsToJSONString(campaigns []*Campaign) string { | ||
var sb strings.Builder | ||
|
||
sb.WriteString("[") | ||
for i, campaign := range campaigns { | ||
if i > 0 { | ||
sb.WriteString(",") | ||
} | ||
|
||
sb.WriteString(campaign.CampaignToJSONString()) | ||
} | ||
sb.WriteString("]") | ||
|
||
return sb.String() | ||
} | ||
|
||
// CampaignToJSONString returns a Campaign formatted as a JSON string | ||
func (c *Campaign) CampaignToJSONString() string { | ||
node := json.ObjectNode("", map[string]*json.Node{ | ||
"Ctype": json.StringNode("Ctype", c.Ctype.String()), | ||
"Title": json.StringNode("Title", c.Title), | ||
"Description": json.StringNode("Description", c.Description), | ||
"Goal": json.NumberNode("Goal", float64(c.Goal)), | ||
"Current": json.NumberNode("Current", float64(c.Current)), | ||
"Begin": json.StringNode("Begin", strconv.Itoa(int(c.Begin.Unix()))), | ||
"Deadline": json.StringNode("Deadline", strconv.Itoa(int(c.Deadline.Unix()))), | ||
"Owner": json.StringNode("Owner", c.Owner.Address.String()), | ||
"Beneficiary": json.StringNode("Beneficiary", c.Beneficiary.Address.String()), | ||
"Contributors": json.NumberNode("Contributors", float64(len(c.contributors))), | ||
}) | ||
value, err := json.Marshal(node) | ||
if err != nil { | ||
panic(ufmt.Sprintf("unexpected error: %s", err)) | ||
} | ||
|
||
return string(value) | ||
} | ||
|
||
func (c Campaign) Render(id string) string { | ||
var b bytes.Buffer | ||
b.WriteString(ufmt.Sprintf("# Campaign %s\n", id)) | ||
b.WriteString(ufmt.Sprintf("## Title: %s\n", c.Title)) | ||
b.WriteString(ufmt.Sprintf("## Description: %s\n", c.Description)) | ||
b.WriteString(ufmt.Sprintf("### Goal: %d GNOT", c.Goal)) | ||
b.WriteString(ufmt.Sprintf("********** Current: %d GNOT\n", c.Current/1_000_000)) | ||
b.WriteString(ufmt.Sprintf("### Begin: %s", c.Begin.String())) | ||
b.WriteString(ufmt.Sprintf(" -------------> Deadline: %s\n", c.Deadline.String())) | ||
b.WriteString(ufmt.Sprintf("### Owner: %s, %s\n", c.Owner.Name, c.Owner.Address.String())) | ||
b.WriteString(ufmt.Sprintf("### Beneficiary: %s, %s\n", c.Beneficiary.Name, c.Beneficiary.Address.String())) | ||
b.WriteString(ufmt.Sprintf("## Last contributors: %d\n", len(c.GetContributors()))) | ||
if contributors := c.GetContributors(); len(c.GetContributors()) != 0 { | ||
length := len(c.GetContributors()) | ||
if length > 10 { | ||
length = 10 | ||
} | ||
|
||
for i := length - 1; i >= 0; i-- { | ||
if contributors[i].GetDisplay() { | ||
b.WriteString( | ||
ufmt.Sprintf( | ||
"### %s: %dugnot, %s\n", contributors[i].user.Name, contributors[i].Amount, contributors[i].Date.String(), | ||
), // added the date of contribution in the display, but adds "m=+1726419880.000000001" after the date =>> the problems comes from time.now(), had to modify and use time.Unix(time.Now().Unix(), 0) to solve the problem. | ||
) | ||
} else { | ||
b.WriteString( | ||
ufmt.Sprintf( | ||
"### Anonymous: %dugnot\n", contributors[i].Amount, | ||
), | ||
) | ||
} | ||
} | ||
} | ||
return b.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package gnofundme | ||
|
||
import ( | ||
"strconv" | ||
"testing" | ||
"time" | ||
|
||
"gno.land/p/demo/testutils" | ||
"gno.land/p/demo/uassert" | ||
"gno.land/r/demo/users" | ||
) | ||
|
||
const ( | ||
ct = ctype(0) | ||
title = "Campaign 1" | ||
description = "Description 1" | ||
goal = uint64(1000) | ||
ownerAddress = testutils.TestAddress("owner") | ||
beneficiaryAddress = testutils.TestAddress("beneficiary") | ||
owner = users.GetUserByName("demo") | ||
beneficiary = users.GetUserByName("gno") | ||
// Test case 1 Valid campaign | ||
begin = time.Now() | ||
deadline = begin.Add(time.Hour * 24) | ||
) | ||
|
||
var campaign = NewCampaign(0, title, description, 1000, begin, deadline, owner, owner) | ||
|
||
func TestNewCampaign(t *testing.T) { | ||
uassert.Equal(t, campaign.Ctype.String(), ct.String()) | ||
|
||
uassert.Equal(t, campaign.Title, title) | ||
uassert.Equal(t, campaign.Description, description) | ||
uassert.Equal(t, campaign.Goal, goal, "goal") | ||
uassert.Equal(t, campaign.Current, uint64(0)) | ||
uassert.Equal(t, strconv.Itoa(int(campaign.Begin.Unix())), strconv.Itoa(int(begin.Unix()))) | ||
uassert.Equal(t, strconv.Itoa(int(campaign.Deadline.Unix())), strconv.Itoa(int(deadline.Unix()))) | ||
uassert.Equal(t, campaign.Owner.Address.String(), owner.Address.String()) | ||
uassert.Equal(t, campaign.Beneficiary.Address.String(), owner.Address.String()) | ||
uassert.Equal(t, len(campaign.GetContributors()), 0) | ||
} | ||
|
||
func TestAddContributor(t *testing.T) { | ||
contributorAddress := testutils.TestAddress("contributor") | ||
user := users.GetUserByName("demo") | ||
var amount uint64 = 500 | ||
display := true | ||
date := time.Unix(time.Now().Unix(), 0) | ||
campaign.AddContributor(user, date, amount, display) | ||
|
||
contributors := campaign.GetContributors() | ||
uassert.Equal(t, campaign.Current, uint64(500)) | ||
|
||
uassert.Equal(t, len(contributors), 1) | ||
|
||
uassert.Equal(t, contributors[0].user.Address.String(), user.Address.String()) | ||
|
||
uassert.Equal(t, contributors[0].Amount, uint64(500)) | ||
} | ||
|
||
func TestCampaignToJSONString(t *testing.T) { | ||
expected := `{"Ctype":"Personal","Title":"Campaign 1","Description":"Description 1","Goal":1000,"Current":500,"Begin":"` + strconv.Itoa(int(begin.Unix())) + `","Deadline":"` + strconv.Itoa(int(deadline.Unix())) + `","Owner":"` + owner.Address.String() + `","Beneficiary":"` + owner.Address.String() + `","Contributors":1}` | ||
|
||
result := campaign.CampaignToJSONString() | ||
uassert.Equal(t, result, expected) | ||
} | ||
|
||
func TestCampaignsToJSONString(t *testing.T) { | ||
campaigns := []*Campaign{campaign, campaign} | ||
campaignjson := `{"Ctype":"Personal","Title":"Campaign 1","Description":"Description 1","Goal":1000,"Current":500,"Begin":"` + strconv.Itoa(int(begin.Unix())) + `","Deadline":"` + strconv.Itoa(int(deadline.Unix())) + `","Owner":"` + owner.Address.String() + `","Beneficiary":"` + owner.Address.String() + `","Contributors":1}` | ||
expected := `[` + campaignjson + `,` + campaignjson + `]` | ||
|
||
result := CampaignsToJSONString(campaigns) | ||
uassert.Equal(t, result, expected) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module gno.land/r/malek_/gnofundme | ||
|
||
require ( | ||
gno.land/p/demo/avl v0.0.0-latest | ||
gno.land/p/demo/uassert v0.0.0-latest | ||
gno.land/p/demo/ufmt v0.0.0-latest | ||
gno.land/p/demo/users v0.0.0-latest | ||
gno.land/p/malek_/gnofundme v0.0.0-latest | ||
gno.land/r/demo/users v0.0.0-latest | ||
) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function now exists in the
strconv
package