Skip to content

Commit

Permalink
add chain id in asset (#954)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thykof authored Jun 6, 2024
1 parent e06f2e2 commit 97e5b40
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 64 deletions.
20 changes: 20 additions & 0 deletions api/server/models/asset_info.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions api/server/restapi/embedded_spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions api/walletApi-V0.yml
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@ definitions:
decimals:
type: integer
minimum: 0
chainID:
type: integer
minimum: 0
x-nullable: false
AssetInfoWithBalance:
allOf:
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/wallet/add_asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (a *addAsset) Handle(params operations.AddAssetParams) middleware.Responder
}

// Add Asset and persist in JSON file.
if err := a.AssetsStore.AddAsset(params.Nickname, params.AssetAddress, *assetInfoFromSC); err != nil {
if err := a.AssetsStore.AddAsset(params.Nickname, *assetInfoFromSC); err != nil {
// Return error occurred while persisting the asset
errorMsg := "Failed to add the asset to the JSON file."
return operations.NewAddAssetInternalServerError().WithPayload(&models.Error{Code: errorAddAssetJSON, Message: errorMsg})
Expand Down
47 changes: 24 additions & 23 deletions internal/handler/wallet/get_all_assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ func (g *getAllAssets) Handle(params operations.GetAllAssetsParams) middleware.R

assetsWithBalance = append(assetsWithBalance, massaAsset)

userAssetData, resp := g.getAssetsData(acc)
if resp != nil {
return resp
nodeInfo, err := network.GetNetworkInfo()
if err != nil {
operations.NewGetAllAssetsInternalServerError().WithPayload(&models.Error{
Code: errorFetchAssetBalance,
Message: fmt.Sprintf("Failed to fetch network info: %s", err.Error()),
})
}

userAssetData := g.getAssetsData(acc, nodeInfo.ChainID)

assetsWithBalance = append(assetsWithBalance, userAssetData...)

sort.Slice(assetsWithBalance, func(i, j int) bool {
Expand Down Expand Up @@ -115,8 +120,8 @@ func (g *getAllAssets) getMASAsset(acc *account.Account) (*assets.AssetInfoWithB

// getAssetsData fetches the balance and dollar value for each asset in the account.
// If user has asset that are deployed on another network, it will not be included.
func (g *getAllAssets) getAssetsData(acc *account.Account) ([]*assets.AssetInfoWithBalances, middleware.Responder) {
assetsInfo := g.AssetsStore.All(acc.Nickname)
func (g *getAllAssets) getAssetsData(acc *account.Account, chainID int) []*assets.AssetInfoWithBalances {
assetsInfo := g.AssetsStore.All(acc.Nickname, chainID)

assetsWithBalance := make([]*assets.AssetInfoWithBalances, 0)
var wg sync.WaitGroup
Expand All @@ -130,13 +135,11 @@ func (g *getAllAssets) getAssetsData(acc *account.Account) ([]*assets.AssetInfoW
go func(asset *assets.AssetInfoWithBalances) {
defer wg.Done()

// First, check if the asset exists in the network
if !g.massaClient.AssetExistInNetwork(asset.AssetInfo.Address) {
logger.Infof("Asset %s does not exist in the network", asset.AssetInfo.Address)
if asset.AssetInfo.Address == "" {
return
}

// Fetch the balance for the current asset
// Fetch the balance and dollar value of the current asset
balance, dollarValue := g.fetchAssetData(asset, acc)

asset.Balance = balance
Expand All @@ -157,7 +160,7 @@ func (g *getAllAssets) getAssetsData(acc *account.Account) ([]*assets.AssetInfoW
mu.Unlock()
}

return assetsWithBalance, nil
return assetsWithBalance
}

func (g *getAllAssets) fetchAssetData(asset *assets.AssetInfoWithBalances, acc *account.Account) (string, *float64) {
Expand Down Expand Up @@ -199,22 +202,20 @@ func convertToModel(assetsWithBalance []*assets.AssetInfoWithBalances) []*models
Decimals: asset.AssetInfo.Decimals,
Name: asset.AssetInfo.Name,
Symbol: asset.AssetInfo.Symbol,
ChainID: asset.AssetInfo.ChainID,
}

newAsset := &models.AssetInfoWithBalance{
AssetInfo: assetInfo,
Balance: asset.Balance,
IsDefault: asset.IsDefault,
}

if asset.DollarValue == nil {
result = append(result, &models.AssetInfoWithBalance{
AssetInfo: assetInfo,
Balance: asset.Balance,
IsDefault: asset.IsDefault,
})
} else {
result = append(result, &models.AssetInfoWithBalance{
AssetInfo: assetInfo,
Balance: asset.Balance,
DollarValue: fmt.Sprintf("%.2f", *asset.DollarValue),
IsDefault: asset.IsDefault,
})
if asset.DollarValue != nil {
newAsset.DollarValue = fmt.Sprintf("%.2f", *asset.DollarValue)
}

result = append(result, newAsset)
}

return result
Expand Down
3 changes: 2 additions & 1 deletion internal/handler/wallet/get_all_assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestGetAllAssetsHandler(t *testing.T) {
assetsWithBalance := getAssets(t, api, nickname)

// Assert that assetsWithBalance contains the expected data
assert.Len(t, assetsWithBalance, 12, "the assets list should have 12 items")
assert.Len(t, assetsWithBalance, 6, "the assets list should have 6 items")

assert.Equal(t, "1000000", assetsWithBalance[0].Balance)
assert.Equal(t, "Massa", assetsWithBalance[0].AssetInfo.Name)
Expand Down Expand Up @@ -55,4 +55,5 @@ func assertAssetInfoWithBalanceEqual(t *testing.T, actual, expected *models.Asse
assert.Equal(t, expected.AssetInfo.Name, actual.AssetInfo.Name)
assert.Equal(t, expected.AssetInfo.Symbol, actual.AssetInfo.Symbol)
assert.Equal(t, expected.AssetInfo.Decimals, actual.AssetInfo.Decimals)
assert.Equal(t, expected.AssetInfo.ChainID, actual.AssetInfo.ChainID)
}
10 changes: 5 additions & 5 deletions internal/handler/wallet/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (w *walletSign) Handle(params operations.SignParams) middleware.Responder {
}
}

operation, msgToSign, err := prepareOperation(acc, fees, params.Body.Operation.String(), promptRequest.Data.(PromptRequestSignData).OperationType, *params.Body.ChainID)
operation, msgToSign, err := prepareOperation(acc, fees, params.Body.Operation.String(), *params.Body.ChainID)
if err != nil {
return newErrorResponse(err.Error(), errorSignDecodeOperation, http.StatusBadRequest)
}
Expand Down Expand Up @@ -203,7 +203,7 @@ func (w *walletSign) Success(acc *account.Account, signature []byte, correlation
// prepareOperation prepares the operation to be signed.
// Returns the modified operation (fees change) and the operation to be signed (with public key).
// Returns an error if the operation cannot be decoded.
func prepareOperation(acc *account.Account, fees uint64, operationB64 string, operationType int, chainID int64) ([]byte, []byte, error) {
func prepareOperation(acc *account.Account, fees uint64, operationB64 string, chainID int64) ([]byte, []byte, error) {
decodedMsg, _, expiry, err := sendoperation.DecodeMessage64(operationB64)
if err != nil {
return nil, nil, fmt.Errorf("failed to decode operation for preparing before signing: %w", err)
Expand Down Expand Up @@ -254,7 +254,7 @@ func (w *walletSign) getPromptRequest(params operations.SignParams, acc *account
data, err = getExecuteSCPromptData(decodedMsg)

case callsc.OpType:
data, err = getCallSCPromptData(decodedMsg, acc)
data, err = getCallSCPromptData(decodedMsg)

default:
return nil, 0, fmt.Errorf("unhandled operation type: %d", opType)
Expand Down Expand Up @@ -282,7 +282,7 @@ func (w *walletSign) getPromptRequest(params operations.SignParams, acc *account
data.OperationType = int(opType)
data.AllowFeeEdition = *params.AllowFeeEdition
data.ChainID = chainID
data.Assets = convertAssetsToModel(w.AssetsStore.All(acc.Nickname))
data.Assets = convertAssetsToModel(w.AssetsStore.All(acc.Nickname, int(chainID)))

promptRequest := prompt.PromptRequest{
Action: walletapp.Sign,
Expand All @@ -294,7 +294,6 @@ func (w *walletSign) getPromptRequest(params operations.SignParams, acc *account

func getCallSCPromptData(
decodedMsg []byte,
acc *account.Account,
) (PromptRequestSignData, error) {
msg, err := callsc.DecodeMessage(decodedMsg)
if err != nil {
Expand Down Expand Up @@ -456,6 +455,7 @@ func convertAssetsToModel(assetsWithBalance []*assets.AssetInfoWithBalances) []m
Decimals: asset.AssetInfo.Decimals,
Name: asset.AssetInfo.Name,
Symbol: asset.AssetInfo.Symbol,
ChainID: asset.AssetInfo.ChainID,
}
result = append(result, assetInfo)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/wallet/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestPrepareOperation(t *testing.T) {
fees := uint64(1000)
operationB64 := "AKT4CASAzuTNAqCNBgEAXBwUw39NBQYix8Ovph0TUiJuDDEnlFYUPgsbeMbrA4cLZm9yd2FyZEJ1cm7FAQDgfY7fLW7qpwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoAAAAweGZDRERBRTI1MTAwNjIxYTViQzg4MTlkQzlEMzg0MjUzNEQ3QmY0NzYAAAAANQAAAEFTMTJUUm9TY01kd0xLOFlwdDZOQkFwcHl6Q0Z3N1FlRzVlM3hGdnhwQ0FuQW5ZTGZ1TVVUKgAAADB4NTM4NDRGOTU3N0MyMzM0ZTU0MUFlYzdEZjcxNzRFQ2U1ZEYxZkNmMKc2qgAAAAAA"

operation, msgToSign, err := prepareOperation(acc, fees, operationB64, 4, ChainIDUnitTests)
operation, msgToSign, err := prepareOperation(acc, fees, operationB64, ChainIDUnitTests)
assert.NoError(t, err)
expected := []byte{0xe8, 0x7, 0xa4, 0xf8, 0x8, 0x4, 0x80, 0xce, 0xe4, 0xcd, 0x2, 0xa0, 0x8d, 0x6, 0x1, 0x0, 0x5c, 0x1c, 0x14, 0xc3, 0x7f, 0x4d, 0x5, 0x6, 0x22, 0xc7, 0xc3, 0xaf, 0xa6, 0x1d, 0x13, 0x52, 0x22, 0x6e, 0xc, 0x31, 0x27, 0x94, 0x56, 0x14, 0x3e, 0xb, 0x1b, 0x78, 0xc6, 0xeb, 0x3, 0x87, 0xb, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x42, 0x75, 0x72, 0x6e, 0xc5, 0x1, 0x0, 0xe0, 0x7d, 0x8e, 0xdf, 0x2d, 0x6e, 0xea, 0xa7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x30, 0x78, 0x66, 0x43, 0x44, 0x44, 0x41, 0x45, 0x32, 0x35, 0x31, 0x30, 0x30, 0x36, 0x32, 0x31, 0x61, 0x35, 0x62, 0x43, 0x38, 0x38, 0x31, 0x39, 0x64, 0x43, 0x39, 0x44, 0x33, 0x38, 0x34, 0x32, 0x35, 0x33, 0x34, 0x44, 0x37, 0x42, 0x66, 0x34, 0x37, 0x36, 0x0, 0x0, 0x0, 0x0, 0x35, 0x0, 0x0, 0x0, 0x41, 0x53, 0x31, 0x32, 0x54, 0x52, 0x6f, 0x53, 0x63, 0x4d, 0x64, 0x77, 0x4c, 0x4b, 0x38, 0x59, 0x70, 0x74, 0x36, 0x4e, 0x42, 0x41, 0x70, 0x70, 0x79, 0x7a, 0x43, 0x46, 0x77, 0x37, 0x51, 0x65, 0x47, 0x35, 0x65, 0x33, 0x78, 0x46, 0x76, 0x78, 0x70, 0x43, 0x41, 0x6e, 0x41, 0x6e, 0x59, 0x4c, 0x66, 0x75, 0x4d, 0x55, 0x54, 0x2a, 0x0, 0x0, 0x0, 0x30, 0x78, 0x35, 0x33, 0x38, 0x34, 0x34, 0x46, 0x39, 0x35, 0x37, 0x37, 0x43, 0x32, 0x33, 0x33, 0x34, 0x65, 0x35, 0x34, 0x31, 0x41, 0x65, 0x63, 0x37, 0x44, 0x66, 0x37, 0x31, 0x37, 0x34, 0x45, 0x43, 0x65, 0x35, 0x64, 0x46, 0x31, 0x66, 0x43, 0x66, 0x30, 0xa7, 0x36, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x0}
assert.Equal(t, expected, operation)
Expand Down
53 changes: 32 additions & 21 deletions pkg/assets/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"path/filepath"
"sync"

"github.com/go-openapi/swag"
"github.com/massalabs/station-massa-wallet/api/server/models"
"github.com/massalabs/station-massa-wallet/pkg/network"
"github.com/massalabs/station-massa-wallet/pkg/wallet"
Expand Down Expand Up @@ -51,6 +52,7 @@ type assetData struct {
Name string `json:"name"`
Symbol string `json:"symbol"`
Decimals int64 `json:"decimals"`
ChainID int64 `json:"chainID"`
}

// NewAssetsStore creates and initializes a new instance of AssetsStore.
Expand Down Expand Up @@ -127,6 +129,7 @@ func (s *AssetsStore) loadAccountsStore() error {
Name: asset.Name,
Symbol: asset.Symbol,
Decimals: &decimals,
ChainID: swag.Int64(asset.ChainID),
}
accountAssets.ContractAssets[asset.ContractAddress] = assetInfo
}
Expand Down Expand Up @@ -176,6 +179,7 @@ func (s *AssetsStore) save() error {
Name: assetInfo.Name,
Symbol: assetInfo.Symbol,
Decimals: *assetInfo.Decimals,
ChainID: *assetInfo.ChainID,
}
assetsData.Assets = append(assetsData.Assets, asset)
}
Expand All @@ -199,9 +203,9 @@ func (s *AssetsStore) save() error {
}

// AddAsset adds the asset information for a given account nickname in the JSON.
func (s *AssetsStore) AddAsset(nickname, assetAddress string, assetInfo models.AssetInfo) error {
func (s *AssetsStore) AddAsset(nickname string, assetInfo models.AssetInfo) error {
// Update the ContractAssets map with the new asset information
s.AddAssetToMemory(nickname, assetAddress, assetInfo)
s.AddAssetToMemory(nickname, assetInfo)

// Synchronize the AssetsStore map to JSON and write to the file
if err := s.save(); err != nil {
Expand All @@ -212,7 +216,7 @@ func (s *AssetsStore) AddAsset(nickname, assetAddress string, assetInfo models.A
}

// AddAssetToMemory adds the asset information for a given account nickname to the AssetsStore.
func (s *AssetsStore) AddAssetToMemory(nickname, assetAddress string, assetInfo models.AssetInfo) {
func (s *AssetsStore) AddAssetToMemory(nickname string, assetInfo models.AssetInfo) {
s.StoreMutex.Lock()
defer s.StoreMutex.Unlock()

Expand All @@ -226,7 +230,7 @@ func (s *AssetsStore) AddAssetToMemory(nickname, assetAddress string, assetInfo
}

// Update the ContractAssets map of the specific *assets.AssetsStore with the new asset information
accountAssets.ContractAssets[assetAddress] = assetInfo
accountAssets.ContractAssets[assetInfo.Address] = assetInfo
s.Assets[nickname] = accountAssets
}

Expand Down Expand Up @@ -264,7 +268,7 @@ func (s *AssetsStore) DeleteAsset(nickname, assetAddress string) error {
// All returns all the assets associated with a specific account nickname.
// It returns the default assets first, followed by the assets added by the user.
// If user already added the default asset, it will not be duplicated.
func (s *AssetsStore) All(nickname string) []*AssetInfoWithBalances {
func (s *AssetsStore) All(nickname string, chainID int) []*AssetInfoWithBalances {
defaultAssets, err := s.Default()
if err != nil {
logger.Errorf("Failed to get default assets: %s", err.Error())
Expand All @@ -276,13 +280,17 @@ func (s *AssetsStore) All(nickname string) []*AssetInfoWithBalances {
includedAddresses := map[string]bool{}

for _, asset := range defaultAssets {
if asset.ChainID != chainID {
continue
}
decimals := asset.Decimals // Copy the decimals value to avoid a pointer to a local variable
completeAsset := &AssetInfoWithBalances{
AssetInfo: &models.AssetInfo{
Address: asset.Address,
Decimals: &decimals,
Name: asset.Name,
Symbol: asset.Symbol,
ChainID: swag.Int64((int64(asset.ChainID))),
},
Balance: "",
MEXCSymbol: asset.MEXCSymbol,
Expand All @@ -295,23 +303,26 @@ func (s *AssetsStore) All(nickname string) []*AssetInfoWithBalances {

// Append default assets ensuring no duplication
for _, asset := range s.Assets[nickname].ContractAssets {
// Append the asset info to the result slice if it is not already in the list
if _, exists := includedAddresses[asset.Address]; !exists {
completeAsset := &AssetInfoWithBalances{
AssetInfo: &models.AssetInfo{
Address: asset.Address,
Decimals: asset.Decimals,
Name: asset.Name,
Symbol: asset.Symbol,
},
Balance: "",
MEXCSymbol: "",
DollarValue: nil,
IsDefault: false,
}
assetsInfo = append(assetsInfo, completeAsset)
includedAddresses[asset.Address] = true
// skip if it's already in the list or not in the same chain
_, exists := includedAddresses[asset.Address]
if *asset.ChainID != int64(chainID) || exists {
continue
}
completeAsset := &AssetInfoWithBalances{
AssetInfo: &models.AssetInfo{
Address: asset.Address,
Decimals: asset.Decimals,
Name: asset.Name,
Symbol: asset.Symbol,
ChainID: asset.ChainID,
},
Balance: "",
MEXCSymbol: "",
DollarValue: nil,
IsDefault: false,
}
assetsInfo = append(assetsInfo, completeAsset)
includedAddresses[asset.Address] = true
}

return assetsInfo
Expand Down
4 changes: 3 additions & 1 deletion pkg/assets/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,18 @@ func TestAddAndDeleteAsset(t *testing.T) {
// Test case 1: Add an asset and check if it's saved to JSON
nickname := "dummyAccount"
assetAddress := "0x1234567890abcdef"
chainID := int64(77658366)
assetInfo := models.AssetInfo{
Address: assetAddress,
Name: "TestToken",
Symbol: "TT",
Decimals: new(int64),
ChainID: &chainID,
}
*assetInfo.Decimals = 18

// Add the asset
err = store.AddAsset(nickname, assetAddress, assetInfo)
err = store.AddAsset(nickname, assetInfo)
assert.NoError(t, err)

// Check if the added asset exists
Expand Down
Loading

0 comments on commit 97e5b40

Please sign in to comment.