Skip to content

Commit

Permalink
Add URI and URIHash to the asset FT. (#685)
Browse files Browse the repository at this point in the history
  • Loading branch information
dzmitryhil authored Oct 26, 2023
1 parent 81fc065 commit c03ed9c
Show file tree
Hide file tree
Showing 19 changed files with 706 additions and 158 deletions.
8 changes: 8 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ EventIssued is emitted on MsgIssue.
| `features` | [Feature](#coreum.asset.ft.v1.Feature) | repeated | |
| `burn_rate` | [string](#string) | | |
| `send_commission_rate` | [string](#string) | | |
| `uri` | [string](#string) | | |
| `uri_hash` | [string](#string) | | |



Expand Down Expand Up @@ -900,6 +902,8 @@ Definition defines the fungible token settings to store.
| `burn_rate` | [string](#string) | | burn_rate is a number between 0 and 1 which will be multiplied by send amount to determine burn_amount. This value will be burnt on top of the send amount. |
| `send_commission_rate` | [string](#string) | | send_commission_rate is a number between 0 and 1 which will be multiplied by send amount to determine amount sent to the token issuer account. |
| `version` | [uint32](#uint32) | | |
| `uri` | [string](#string) | | |
| `uri_hash` | [string](#string) | | |



Expand Down Expand Up @@ -940,6 +944,8 @@ Token is a full representation of the fungible token.
| `burn_rate` | [string](#string) | | burn_rate is a number between 0 and 1 which will be multiplied by send amount to determine burn_amount. This value will be burnt on top of the send amount. |
| `send_commission_rate` | [string](#string) | | send_commission_rate is a number between 0 and 1 which will be multiplied by send amount to determine amount sent to the token issuer account. |
| `version` | [uint32](#uint32) | | |
| `uri` | [string](#string) | | |
| `uri_hash` | [string](#string) | | |



Expand Down Expand Up @@ -1101,6 +1107,8 @@ MsgIssue defines message to issue new fungible token.
| `features` | [Feature](#coreum.asset.ft.v1.Feature) | repeated | |
| `burn_rate` | [string](#string) | | burn_rate is a number between 0 and 1 which will be multiplied by send amount to determine burn_amount. This value will be burnt on top of the send amount. |
| `send_commission_rate` | [string](#string) | | send_commission_rate is a number between 0 and 1 which will be multiplied by send amount to determine amount sent to the token issuer account. |
| `uri` | [string](#string) | | |
| `uri_hash` | [string](#string) | | |



Expand Down
6 changes: 6 additions & 0 deletions docs/static/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -7205,6 +7205,12 @@
"version": {
"type": "integer",
"format": "int64"
},
"uri": {
"type": "string"
},
"uri_hash": {
"type": "string"
}
},
"description": "Token is a full representation of the fungible token."
Expand Down
10 changes: 8 additions & 2 deletions integration-tests/modules/assetft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ func TestAssetFTIssue(t *testing.T) {
Description: "ABC Description",
InitialAmount: sdkmath.NewInt(1000),
Features: []assetfttypes.Feature{},
URI: "https://my-class-meta.invalid/1",
URIHash: "content-hash",
}

res, err := client.BroadcastTx(
Expand Down Expand Up @@ -250,6 +252,8 @@ func TestAssetIssueAndQueryTokens(t *testing.T) {
InitialAmount: sdkmath.NewInt(777),
BurnRate: sdk.NewDec(0),
SendCommissionRate: sdk.NewDec(0),
URI: "https://my-class-meta.invalid/1",
URIHash: "content-hash",
}

_, err := client.BroadcastTx(
Expand Down Expand Up @@ -284,12 +288,14 @@ func TestAssetIssueAndQueryTokens(t *testing.T) {
Denom: denom,
Issuer: issuer1.String(),
Symbol: msg1.Symbol,
Subunit: "wsatoshi",
Precision: 8,
Subunit: msg1.Subunit,
Precision: msg1.Precision,
Description: msg1.Description,
BurnRate: msg1.BurnRate,
SendCommissionRate: msg1.SendCommissionRate,
Version: gotToken.Tokens[0].Version, // test should work with all versions
URI: msg1.URI,
URIHash: msg1.URIHash,
}, gotToken.Tokens[0])
}

Expand Down
69 changes: 69 additions & 0 deletions integration-tests/upgrade/ft_new_attributes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//go:build integrationtests

package upgrade

import (
"testing"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

integrationtests "github.com/CoreumFoundation/coreum/v3/integration-tests"
"github.com/CoreumFoundation/coreum/v3/pkg/client"
"github.com/CoreumFoundation/coreum/v3/testutil/integration"
assetfttypes "github.com/CoreumFoundation/coreum/v3/x/asset/ft/types"
)

type ftURIAttributesTest struct {
token assetfttypes.Token
}

func (ftt *ftURIAttributesTest) Before(t *testing.T) {
ctx, chain := integrationtests.NewCoreumTestingContext(t)
requireT := require.New(t)
assetftClient := assetfttypes.NewQueryClient(chain.ClientContext)

issuer := chain.GenAccount()
chain.FundAccountWithOptions(ctx, t, issuer, integration.BalancesOptions{
Messages: []sdk.Msg{
&assetfttypes.MsgIssue{},
},
Amount: chain.QueryAssetFTParams(ctx, t).IssueFee.Amount,
})

issueMsg := &assetfttypes.MsgIssue{
Issuer: issuer.String(),
Symbol: "ABC",
Subunit: "uabc",
Precision: 6,
Description: "ABC Description",
InitialAmount: sdkmath.NewInt(1000),
Features: []assetfttypes.Feature{},
}
_, err := client.BroadcastTx(
ctx,
chain.ClientContext.WithFromAddress(issuer),
chain.TxFactory().WithGas(chain.GasLimitByMsgs(issueMsg)),
issueMsg,
)
requireT.NoError(err)
tokenRes, err := assetftClient.Token(ctx, &assetfttypes.QueryTokenRequest{
Denom: assetfttypes.BuildDenom(issueMsg.Subunit, issuer),
})
requireT.NoError(err)
ftt.token = tokenRes.Token
}

func (ftt *ftURIAttributesTest) After(t *testing.T) {
ctx, chain := integrationtests.NewCoreumTestingContext(t)
requireT := require.New(t)
assetftClient := assetfttypes.NewQueryClient(chain.ClientContext)

// check that prev token is available we can query it
tokenRes, err := assetftClient.Token(ctx, &assetfttypes.QueryTokenRequest{
Denom: ftt.token.Denom,
})
requireT.NoError(err)
require.Equal(t, ftt.token, tokenRes.Token)
}
1 change: 1 addition & 0 deletions integration-tests/upgrade/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func upgradeV3(t *testing.T) {
&ibcUpgradeTest{},
&govMigrationTest{},
&nftMigrationTest{},
&ftURIAttributesTest{},
}

for _, test := range tests {
Expand Down
2 changes: 2 additions & 0 deletions proto/coreum/asset/ft/v1/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ message EventIssued {
(gogoproto.nullable) = false,
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec"
];
string uri = 11 [(gogoproto.customname) = "URI"];
string uri_hash = 12 [(gogoproto.customname) = "URIHash"];
}

message EventFrozenAmountChanged {
Expand Down
4 changes: 4 additions & 0 deletions proto/coreum/asset/ft/v1/token.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ message Definition {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec"
];
uint32 version = 6;
string uri = 7 [(gogoproto.customname) = "URI"];
string uri_hash = 8 [(gogoproto.customname) = "URIHash"];
}

// Token is a full representation of the fungible token.
Expand Down Expand Up @@ -62,6 +64,8 @@ message Token {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec"
];
uint32 version = 11;
string uri = 12 [(gogoproto.customname) = "URI"];
string uri_hash = 13 [(gogoproto.customname) = "URIHash"];
}

// DelayedTokenUpgradeV1 is executed by the delay module when it's time to enable IBC.
Expand Down
4 changes: 3 additions & 1 deletion proto/coreum/asset/ft/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ message MsgIssue {
(gogoproto.nullable) = false,
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec"
];
string uri = 10 [(gogoproto.customname) = "URI"];
string uri_hash = 11 [(gogoproto.customname) = "URIHash"];
}

message MsgMint {
Expand Down Expand Up @@ -130,7 +132,7 @@ message MsgUpgradeTokenV1 {

message MsgUpdateParams {
option (cosmos.msg.v1.signer) = "authority";
option (amino.name) = "cosmos-sdk/MsgUpdateParams";
option (amino.name) = "cosmos-sdk/MsgUpdateParams";

string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
Params params = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
Expand Down
2 changes: 2 additions & 0 deletions x/asset/ft/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
BurnRate: token.BurnRate,
SendCommissionRate: token.SendCommissionRate,
Version: token.Version,
URI: token.URI,
URIHash: token.URIHash,
}

k.SetDefinition(ctx, issuer, subunit, definition)
Expand Down
28 changes: 19 additions & 9 deletions x/asset/ft/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,35 @@ func TestInitAndExportGenesis(t *testing.T) {
var pendingTokenUpgrades []types.PendingTokenUpgrade
for i := uint32(0); i < 5; i++ {
token := types.Token{
Denom: types.BuildDenom(fmt.Sprintf("abc%d", i), issuer),
Issuer: issuer.String(),
Symbol: fmt.Sprintf("ABC%d", i),
Subunit: fmt.Sprintf("abc%d", i),
Precision: uint32(rand.Int31n(19) + 1),
BurnRate: sdk.MustNewDecFromStr(fmt.Sprintf("0.%d", i)),
SendCommissionRate: sdk.MustNewDecFromStr(fmt.Sprintf("0.%d", i+1)),
Denom: types.BuildDenom(fmt.Sprintf("abc%d", i), issuer),
Issuer: issuer.String(),
Symbol: fmt.Sprintf("ABC%d", i),
Subunit: fmt.Sprintf("abc%d", i),
Precision: uint32(rand.Int31n(19) + 1),
Description: fmt.Sprintf("DESC%d", i),
Features: []types.Feature{
types.Feature_freezing,
types.Feature_whitelisting,
},
Version: i,
BurnRate: sdk.MustNewDecFromStr(fmt.Sprintf("0.%d", i)),
SendCommissionRate: sdk.MustNewDecFromStr(fmt.Sprintf("0.%d", i+1)),
Version: i,
URI: fmt.Sprintf("https://my-class-meta.invalid/%d", i),
URIHash: fmt.Sprintf("content-hash%d", i),
}
// Globally freeze some Tokens.
if i%2 == 0 {
token.GloballyFrozen = true
}
tokens = append(tokens, token)
requireT.NoError(ftKeeper.SetDenomMetadata(ctx, token.Denom, token.Symbol, token.Description, token.Precision))
requireT.NoError(ftKeeper.SetDenomMetadata(
ctx,
token.Denom,
token.Symbol,
token.Description,
token.URI,
token.URIHash,
token.Precision))
if i == 0 {
pendingTokenUpgrades = append(pendingTokenUpgrades, types.PendingTokenUpgrade{
Denom: token.Denom,
Expand Down
33 changes: 26 additions & 7 deletions x/asset/ft/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,19 @@ func (k Keeper) IssueVersioned(ctx sdk.Context, settings types.IssueSettings, ve
BurnRate: settings.BurnRate,
SendCommissionRate: settings.SendCommissionRate,
Version: version,
}

if err := k.SetDenomMetadata(ctx, denom, settings.Symbol, settings.Description, settings.Precision); err != nil {
URI: settings.URI,
URIHash: settings.URIHash,
}

if err := k.SetDenomMetadata(
ctx,
denom,
settings.Symbol,
settings.Description,
settings.URI,
settings.URIHash,
settings.Precision,
); err != nil {
return "", err
}

Expand All @@ -238,6 +248,8 @@ func (k Keeper) IssueVersioned(ctx sdk.Context, settings types.IssueSettings, ve
Features: settings.Features,
BurnRate: settings.BurnRate,
SendCommissionRate: settings.SendCommissionRate,
URI: settings.URI,
URIHash: settings.URIHash,
}); err != nil {
return "", sdkerrors.Wrapf(types.ErrInvalidState, "failed to emit EventIssued event: %s", err)
}
Expand All @@ -264,12 +276,13 @@ func (k Keeper) SetDefinition(ctx sdk.Context, issuer sdk.AccAddress, subunit st
}

// SetDenomMetadata registers denom metadata on the bank keeper.
func (k Keeper) SetDenomMetadata(ctx sdk.Context, denom, symbol, description string, precision uint32) error {
func (k Keeper) SetDenomMetadata(
ctx sdk.Context,
denom, symbol, description, uri, uriHash string,
precision uint32,
) error {
denomMetadata := banktypes.Metadata{
Name: symbol,
Symbol: symbol,
Description: description,

// This is a cosmos sdk requirement that the first denomination unit MUST be the base
DenomUnits: []*banktypes.DenomUnit{
{
Expand All @@ -285,6 +298,10 @@ func (k Keeper) SetDenomMetadata(ctx sdk.Context, denom, symbol, description str
// and we take the symbol provided by the user and use it as symbol
Base: denom,
Display: symbol,
Name: symbol,
Symbol: symbol,
URI: uri,
URIHash: uriHash,
}

if err := denomMetadata.Validate(); err != nil {
Expand Down Expand Up @@ -742,6 +759,8 @@ func (k Keeper) getTokenFullInfo(ctx sdk.Context, definition types.Definition) (
SendCommissionRate: definition.SendCommissionRate,
GloballyFrozen: k.isGloballyFrozen(ctx, definition.Denom),
Version: definition.Version,
URI: definition.URI,
URIHash: definition.URIHash,
}, nil
}

Expand Down
6 changes: 6 additions & 0 deletions x/asset/ft/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ func TestKeeper_Issue(t *testing.T) {
Precision: 8,
InitialAmount: sdkmath.NewInt(777),
Features: []types.Feature{types.Feature_freezing},
URI: "https://my-class-meta.invalid/1",
URIHash: "content-hash",
}

denom, err := ftKeeper.Issue(ctx, settings)
Expand Down Expand Up @@ -81,6 +83,8 @@ func TestKeeper_Issue(t *testing.T) {
BurnRate: sdk.NewDec(0),
SendCommissionRate: sdk.NewDec(0),
Version: types.CurrentTokenVersion,
URI: settings.URI,
URIHash: settings.URIHash,
}, gotToken)

// check the metadata
Expand All @@ -102,6 +106,8 @@ func TestKeeper_Issue(t *testing.T) {
},
Base: denom,
Display: settings.Symbol,
URI: settings.URI,
URIHash: settings.URIHash,
}, storedMetadata)

// check the account state
Expand Down
2 changes: 2 additions & 0 deletions x/asset/ft/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ func (ms MsgServer) Issue(ctx context.Context, req *types.MsgIssue) (*types.Empt
Features: req.Features,
BurnRate: req.BurnRate,
SendCommissionRate: req.SendCommissionRate,
URI: req.URI,
URIHash: req.URIHash,
})
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit c03ed9c

Please sign in to comment.