-
Notifications
You must be signed in to change notification settings - Fork 417
feat: r/coins
balance checker
#3899
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
Merged
Merged
Changes from 9 commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
c59d58d
feat(examples): add r/gnoland/coins
moul a654e50
feat: TotalCoin
notJoon df1bf50
Merge branch 'master' into airdrop-checker
notJoon c0b825a
fix
notJoon b12bbe7
test: mock TotalCoin
notJoon ee072ef
fmt
notJoon 9cb5c81
fix
notJoon dc636d3
fix: create proper denom
notJoon ef43e83
doc
notJoon 695412e
fix
notJoon 0e325f3
remove nav
notJoon 0d751b6
use IterateAccounts
notJoon 15296c5
airdrop things
notJoon f150093
Revert "airdrop things"
notJoon bd3eb64
render funcs
notJoon 99fb5b7
Merge branch 'master' into airdrop-checker
notJoon 0c8d344
use md package
notJoon 6f00822
supply keeper
notJoon 8b09a6a
Merge branch 'master' into airdrop-checker
notJoon 5c175b2
docs
notJoon b535661
test: SDKBanker
notJoon bd710bd
remove unused
notJoon 07584c3
Merge branch 'master' into airdrop-checker
notJoon aa509df
Merge branch 'master' into airdrop-checker
notJoon 4bddb4a
fix
notJoon bfee6be
Revert "supply keeper"
notJoon c5a012b
Merge branch 'master' into airdrop-checker
notJoon 4cbd61c
fix
notJoon cb9a437
fix
notJoon 8efad65
use mux
notJoon 468a717
fix
notJoon 7b5d23e
Merge branch 'master' into airdrop-checker
notJoon 41ecdaf
start from the beginning
notJoon 1978a90
simple r/coins
notJoon b5893d6
disable totalsupply
notJoon f20a4d6
Merge branch 'master' into airdrop-checker
notJoon dc45336
fmt
notJoon b451b9a
Merge branch 'master' into airdrop-checker
moul a357a08
Update examples/gno.land/r/gnoland/coins/coins.gno
notJoon c1b246d
Apply suggestions from code review
notJoon 16ed599
fix
notJoon b713afd
remove unnecessary package
notJoon 1398f4f
Merge branch 'master' into airdrop-checker
notJoon 28c00d1
fix
notJoon 55d979d
remove redundant return
notJoon 6b5d146
Merge branch 'master' into airdrop-checker
thehowl 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 hidden or 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,112 @@ | ||
// Package coins provides simple helpers to retrieve information about coins | ||
// on the Gno.land blockchain. | ||
// | ||
// The primary goal of this realm is to allow users to check their token balances without | ||
// relying on external tools or services. This is particularly valuable for new networks | ||
// that aren't yet widely supported by public explorers or wallets. By using this realm, | ||
// users can always access their balance information directly through the gnodev. | ||
// | ||
// While currently focused on basic balance checking functionality, this realm could | ||
// potentially be extended to support other banker-related workflows in the future. | ||
// However, we aim to keep it minimal and focused on its core purpose. | ||
// | ||
// This is a "Render-only realm" - it exposes only a Render function as its public | ||
// interface and doesn't maintain any state of its own. This pattern allows for | ||
// simple, stateless information retrieval directly through the blockchain's | ||
// rendering capabilities. | ||
// | ||
// Example usage: | ||
// | ||
// /r/gnoland/coins:ugnot - shows the total supply of ugnot | ||
// /r/gnoland/coins:ugnot/g1... - shows the ugnot balance of a specific address | ||
package coins | ||
|
||
import ( | ||
"std" | ||
"strings" | ||
) | ||
|
||
// TotalSupply returns the total supply of the specified denomination | ||
func TotalSupply(banker std.Banker, denom string) int64 { | ||
if denom == "" { | ||
panic("empty denom") | ||
} | ||
// make the coin's denom to follow the correct format | ||
qualifiedDenom := std.CurrentRealm().CoinDenom(denom) | ||
return banker.TotalCoin(qualifiedDenom) | ||
} | ||
|
||
// AddressBalance returns the balance of the specified token for the given address | ||
func AddressBalance(banker std.Banker, denom string, address std.Address) int64 { | ||
if denom == "" { | ||
panic("empty denom") | ||
} | ||
if !address.IsValid() { | ||
panic("invalid address") | ||
} | ||
return banker.GetCoins(address).AmountOf(denom) | ||
} | ||
|
||
// Path parsing logic: | ||
// - Empty path: Show homepage with general info and usage instructions | ||
// - "<denom>": Show total supply and info about the specified coin | ||
// - "<denom>/<address>": Show specific address balance for the given coin | ||
func Render(path string) string { | ||
banker := std.NewBanker(std.BankerTypeReadonly) | ||
|
||
if path == "" { | ||
return renderHomepage() | ||
} | ||
|
||
if !strings.Contains(path, "/") { | ||
denom := path | ||
totalSupply := TotalSupply(banker, denom) | ||
return renderCoinInfo(denom, totalSupply) | ||
} | ||
|
||
parts := strings.Split(path, "/") | ||
if len(parts) != 2 { | ||
panic("invalid path") | ||
} | ||
|
||
denom, addr := parts[0], parts[1] | ||
return renderAddressBalance(banker, denom, std.Address(addr)) | ||
|
||
// TODO: implement an explanatory homepage that shows usage instructions | ||
// TODO: implement a coin info page showing total supply, and other metrics if we have them | ||
// TODO: implement an address page showing balance for specified coin | ||
// TODO: create navigation links between pages to enable intuitive exploration without typing URLs | ||
leohhhn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
func renderHomepage() string { | ||
return `# Gno.land Coins | ||
thehowl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
` | ||
} | ||
|
||
func renderCoinInfo(denom string, totalSupply int64) string { | ||
return `# Coin Info | ||
|
||
## Denom | ||
` + denom + ` | ||
|
||
## Total Supply | ||
` + std.NewCoin(denom, totalSupply).String() + ` | ||
|
||
[Back to Home](/r/gnoland/coins:) | ||
thehowl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
` | ||
} | ||
|
||
func renderAddressBalance(banker std.Banker, denom string, address std.Address) string { | ||
balance := AddressBalance(banker, denom, address) | ||
return `# Address Balance | ||
|
||
## Address | ||
` + address.String() + ` | ||
|
||
## Balance | ||
` + std.NewCoin(denom, balance).String() + ` | ||
|
||
[Back to Coin Info](/r/gnoland/coins:` + denom + `) | ||
[Back to Home](/r/gnoland/coins:) | ||
thehowl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
` | ||
} |
This file contains hidden or 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,67 @@ | ||
package coins | ||
|
||
import ( | ||
"std" | ||
"strings" | ||
"testing" | ||
|
||
"gno.land/p/demo/testutils" | ||
) | ||
|
||
func TestAirdropChecker(t *testing.T) { | ||
addr1 := testutils.TestAddress("addr1") | ||
addr2 := testutils.TestAddress("addr2") | ||
|
||
realm := std.CurrentRealm() | ||
testDenom := realm.CoinDenom("test") | ||
test2Denom := realm.CoinDenom("test2") | ||
|
||
tests := []struct { | ||
name string | ||
path string | ||
setupFunc func(std.Banker) | ||
expected string | ||
wantPanic bool | ||
}{ | ||
{ | ||
name: "homepage shows supported tokens", | ||
path: "", | ||
setupFunc: func(banker std.Banker) { | ||
banker.IssueCoin(addr1, test2Denom, 1000) | ||
banker.IssueCoin(addr2, test2Denom, 1000) | ||
}, | ||
expected: `# Gno.land Coins`, | ||
}, | ||
{ | ||
name: "show total supply for test token", | ||
path: "test", | ||
setupFunc: func(banker std.Banker) { | ||
banker.IssueCoin(addr1, testDenom, 1000000) | ||
banker.IssueCoin(addr2, testDenom, 500000) | ||
|
||
println("setup amount", banker.TotalCoin(testDenom)) | ||
}, | ||
expected: `1500000test`, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
banker := std.NewBanker(std.BankerTypeRealmIssue) | ||
thehowl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
tt.setupFunc(banker) | ||
|
||
if tt.wantPanic { | ||
defer func() { | ||
if r := recover(); r == nil { | ||
t.Errorf("expected panic for %s", tt.name) | ||
} | ||
}() | ||
} | ||
|
||
result := Render(tt.path) | ||
if !tt.wantPanic { | ||
thehowl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if !strings.Contains(result, tt.expected) { | ||
t.Errorf("expected %s to contain %s", result, tt.expected) | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or 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 @@ | ||
module gno.land/r/gnoland/coins |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
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.
Uh oh!
There was an error while loading. Please reload this page.