Skip to content

Commit

Permalink
add GetTokenVersion and types.TokenVersion (#68)
Browse files Browse the repository at this point in the history
* move `GetTokenVersion` and `configuration.TokenVersion` from https://github.com/trustwallet/backend/blob/master/internal/repository/postgres/models/token.go#L57-L90 to `go-primitives`

* Rename `TokenVersionNext` to `TokenVersionUndefined`, and add test to make sure every tokentype has a tokenversion implemented

* * Change GetTokenVersion signature so that it can return error now
* Added Token Versions for KRC20, RONIN, BEP8, WAVES, STELLAR, NRC20

* Return ErrUnknownTokenType when given string is not a supported tokenType

* Remove unused TokenVersionLatest
  • Loading branch information
Teddy Budiono Hermawan authored Jun 3, 2022
1 parent a7d8b52 commit 8cc2a53
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 1 deletion.
77 changes: 76 additions & 1 deletion types/token.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package types

import (
"errors"
"fmt"
"strconv"

"github.com/trustwallet/go-primitives/asset"
"github.com/trustwallet/go-primitives/coin"
)

var ErrUnknownTokenType = errors.New("unknown token type")
var errTokenVersionNotImplemented = errors.New("token version not implemented")

type (
TokenType string
TokenType string
TokenVersion int

// Token describes the non-native tokens.
// Examples: ERC-20, TRC-20, BEP-2
Expand Down Expand Up @@ -69,6 +74,19 @@ const (
STELLAR TokenType = "STELLAR"
KRC20 TokenType = "KRC20"
AURORA TokenType = "AURORA"

TokenVersionV0 TokenVersion = 0
TokenVersionV1 TokenVersion = 1
TokenVersionV3 TokenVersion = 3
TokenVersionV4 TokenVersion = 4
TokenVersionV5 TokenVersion = 5
TokenVersionV6 TokenVersion = 6
TokenVersionV7 TokenVersion = 7
TokenVersionV8 TokenVersion = 8
TokenVersionV9 TokenVersion = 9
TokenVersionV10 TokenVersion = 10
TokenVersionV11 TokenVersion = 11
TokenVersionUndefined TokenVersion = -1
)

func GetTokenTypes() []TokenType {
Expand Down Expand Up @@ -170,6 +188,63 @@ func GetTokenType(c uint, tokenID string) (string, bool) {
}
}

func GetTokenVersion(tokenType string) (TokenVersion, error) {
parsedTokenType, err := ParseTokenTypeFromString(tokenType)
if err != nil {
return TokenVersionUndefined, err
}
switch parsedTokenType {
case ERC20,
BEP2,
BEP20,
BEP8,
ETC20,
POA20,
CLO20,
TRC10,
TRC21,
WAN20,
GO20,
TT20,
WAVES:
return TokenVersionV0, nil
case TRC20:
return TokenVersionV1, nil
case SPL, KAVA:
return TokenVersionV3, nil
case POLYGON:
return TokenVersionV4, nil
case AVALANCHE, ARBITRUM, FANTOM, HRC20, OPTIMISM, XDAI:
return TokenVersionV5, nil
case TERRA:
return TokenVersionV6, nil
case CELO, NRC20:
return TokenVersionV7, nil
case CW20:
return TokenVersionV8, nil
case ESDT, CRC20:
return TokenVersionV9, nil
case KRC20, STELLAR:
return TokenVersionV10, nil
case RONIN:
return TokenVersionV11, nil
case ERC721, ERC1155, EOS, NEP5, VET, ONTOLOGY, THETA, TOMO, POA, OASIS, AURORA:
return TokenVersionUndefined, nil
default:
// This should not happen, as it is guarded by TestGetTokenVersionImplementEverySupportedTokenTypes
return TokenVersionUndefined, fmt.Errorf("tokenType %s: %w", parsedTokenType, errTokenVersionNotImplemented)
}
}

func ParseTokenTypeFromString(t string) (TokenType, error) {
for _, knownTokenType := range GetTokenTypes() {
if string(knownTokenType) == t {
return knownTokenType, nil
}
}
return "", fmt.Errorf("%s: %w", t, ErrUnknownTokenType)
}

func GetEthereumTokenTypeByIndex(coinIndex uint) (TokenType, error) {
var tokenType TokenType
switch coinIndex {
Expand Down
108 changes: 108 additions & 0 deletions types/token_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"errors"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -267,3 +268,110 @@ func TestGetTokenType(t *testing.T) {
})
}
}

func TestGetTokenVersion(t *testing.T) {
type args struct {
t string
}
tests := []struct {
name string
args args
wantVersion TokenVersion
wantErr error
}{
{
"ERC20 token version",
args{t: string(ERC20)},
TokenVersionV0,
nil,
},
{
"SPL token version",
args{t: string(SPL)},
TokenVersionV3,
nil,
},
{
"Polygon token version",
args{t: string(POLYGON)},
TokenVersionV4,
nil,
},
{
"Fantom token version",
args{t: string(FANTOM)},
TokenVersionV5,
nil,
},
{
"Terra token version",
args{t: "TERRA"},
TokenVersionV6,
nil,
},
{
"CELO token version",
args{t: "CELO"},
TokenVersionV7,
nil,
},
{
"CW20 token version",
args{t: "CW20"},
TokenVersionV8,
nil,
},
{
"CRC20 token version",
args{t: "CRC20"},
TokenVersionV9,
nil,
},
{
"ESDT token version",
args{t: "ESDT"},
TokenVersionV9,
nil,
},
{
"KRC20 token version",
args{t: "KRC20"},
TokenVersionV10,
nil,
},
{
"RONIN token version",
args{t: "RONIN"},
TokenVersionV11,
nil,
},
{
"OASIS token version",
args{t: "OASIS"},
TokenVersionUndefined,
nil,
},
{
"Random token version",
args{t: "Random"},
TokenVersionUndefined,
ErrUnknownTokenType,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, gotErr := GetTokenVersion(tt.args.t)
assert.Equal(t, tt.wantVersion, got)
assert.True(t, errors.Is(gotErr, tt.wantErr))
})
}
}

// TestGetTokenVersionImplementEverySupportedTokenTypes makes sure every supported token type has a version.
// This also makes sure when we add new token type, we remember to add a version for it
func TestGetTokenVersionImplementEverySupportedTokenTypes(t *testing.T) {
for _, tokenType := range GetTokenTypes() {
_, err := GetTokenVersion(string(tokenType))
assert.NoError(t, err)
}
}

0 comments on commit 8cc2a53

Please sign in to comment.