Skip to content

Commit

Permalink
feat_: recovery retracking pending transsactions
Browse files Browse the repository at this point in the history
Add ReTrackOwnerTokenDeploymentTransaction function which will runs community tokens transactions listening.
Add deployment transaction hash to community_tokens table.

Issue #14699
  • Loading branch information
endulab committed May 28, 2024
1 parent edc65e4 commit ad9032d
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 21 deletions.
20 changes: 10 additions & 10 deletions protocol/communities/persistence.go
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ func (p *Persistence) GetCommunityChatIDs(communityID types.HexBytes) ([]string,
func (p *Persistence) GetAllCommunityTokens() ([]*token.CommunityToken, error) {
rows, err := p.db.Query(`SELECT community_id, address, type, name, symbol, description, supply_str,
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals,
deployer, privileges_level FROM community_tokens`)
deployer, privileges_level, tx_hash FROM community_tokens`)
if err != nil {
return nil, err
}
Expand All @@ -1253,7 +1253,7 @@ func (p *Persistence) GetAllCommunityTokens() ([]*token.CommunityToken, error) {
func (p *Persistence) GetCommunityTokens(communityID string) ([]*token.CommunityToken, error) {
rows, err := p.db.Query(`SELECT community_id, address, type, name, symbol, description, supply_str,
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals,
deployer, privileges_level
deployer, privileges_level, tx_hash
FROM community_tokens WHERE community_id = ?`, communityID)
if err != nil {
return nil, err
Expand All @@ -1267,11 +1267,11 @@ func (p *Persistence) GetCommunityToken(communityID string, chainID int, address
token := token.CommunityToken{}
var supplyStr string
err := p.db.QueryRow(`SELECT community_id, address, type, name, symbol, description, supply_str, infinite_supply,
transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level
transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level, tx_hash
FROM community_tokens WHERE community_id = ? AND chain_id = ? AND address = ?`, communityID, chainID, address).Scan(&token.CommunityID, &token.Address, &token.TokenType, &token.Name,
&token.Symbol, &token.Description, &supplyStr, &token.InfiniteSupply, &token.Transferable,
&token.RemoteSelfDestruct, &token.ChainID, &token.DeployState, &token.Base64Image, &token.Decimals,
&token.Deployer, &token.PrivilegesLevel)
&token.Deployer, &token.PrivilegesLevel, &token.TransactionHash)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
Expand All @@ -1290,11 +1290,11 @@ func (p *Persistence) GetCommunityTokenByChainAndAddress(chainID int, address st
token := token.CommunityToken{}
var supplyStr string
err := p.db.QueryRow(`SELECT community_id, address, type, name, symbol, description, supply_str, infinite_supply,
transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level
transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level, tx_hash
FROM community_tokens WHERE chain_id = ? AND address = ?`, chainID, address).Scan(&token.CommunityID, &token.Address, &token.TokenType, &token.Name,
&token.Symbol, &token.Description, &supplyStr, &token.InfiniteSupply, &token.Transferable,
&token.RemoteSelfDestruct, &token.ChainID, &token.DeployState, &token.Base64Image, &token.Decimals,
&token.Deployer, &token.PrivilegesLevel)
&token.Deployer, &token.PrivilegesLevel, &token.TransactionHash)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
Expand All @@ -1318,7 +1318,7 @@ func (p *Persistence) getCommunityTokensInternal(rows *sql.Rows) ([]*token.Commu
err := rows.Scan(&token.CommunityID, &token.Address, &token.TokenType, &token.Name,
&token.Symbol, &token.Description, &supplyStr, &token.InfiniteSupply, &token.Transferable,
&token.RemoteSelfDestruct, &token.ChainID, &token.DeployState, &token.Base64Image, &token.Decimals,
&token.Deployer, &token.PrivilegesLevel)
&token.Deployer, &token.PrivilegesLevel, &token.TransactionHash)
if err != nil {
return nil, err
}
Expand All @@ -1345,10 +1345,10 @@ func (p *Persistence) HasCommunityToken(communityID string, address string, chai

func (p *Persistence) AddCommunityToken(token *token.CommunityToken) error {
_, err := p.db.Exec(`INSERT INTO community_tokens (community_id, address, type, name, symbol, description, supply_str,
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, token.CommunityID, token.Address, token.TokenType, token.Name,
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level, tx_hash)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, token.CommunityID, token.Address, token.TokenType, token.Name,
token.Symbol, token.Description, token.Supply.String(), token.InfiniteSupply, token.Transferable, token.RemoteSelfDestruct,
token.ChainID, token.DeployState, token.Base64Image, token.Decimals, token.Deployer, token.PrivilegesLevel)
token.ChainID, token.DeployState, token.Base64Image, token.Decimals, token.Deployer, token.PrivilegesLevel, token.TransactionHash)
return err
}

Expand Down
3 changes: 3 additions & 0 deletions protocol/communities/persistence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ func (s *PersistenceSuite) TestGetCommunityToken() {
ChainID: 1,
DeployState: token.InProgress,
Base64Image: "ABCD",
TransactionHash: "0x1234",
}

err = s.db.AddCommunityToken(&tokenERC721)
Expand Down Expand Up @@ -426,6 +427,7 @@ func (s *PersistenceSuite) TestGetCommunityTokens() {
Base64Image: "ABCD",
Deployer: "0xDep1",
PrivilegesLevel: token.OwnerLevel,
TransactionHash: "0x1234",
}

tokenERC20 := token.CommunityToken{
Expand All @@ -445,6 +447,7 @@ func (s *PersistenceSuite) TestGetCommunityTokens() {
Decimals: 21,
Deployer: "0xDep2",
PrivilegesLevel: token.CommunityLevel,
TransactionHash: "0x123456",
}

err = s.db.AddCommunityToken(&tokenERC721)
Expand Down
1 change: 1 addition & 0 deletions protocol/communities/token/community_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ type CommunityToken struct {
Decimals int `json:"decimals"`
Deployer string `json:"deployer"`
PrivilegesLevel PrivilegesLevel `json:"privilegesLevel"`
TransactionHash string `json:"transactionHash"`
}
31 changes: 27 additions & 4 deletions protocol/migrations/migrations.go

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

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE community_tokens ADD COLUMN tx_hash TEXT DEFAULT "";
13 changes: 9 additions & 4 deletions services/communitytokens/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deployme
}

savedCommunityToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), deploymentParameters, txArgs.From.Hex(), address.Hex(),
protobuf.CommunityTokenType_ERC721, token.CommunityLevel)
protobuf.CommunityTokenType_ERC721, token.CommunityLevel, tx.Hash().Hex())
if err != nil {
return DeploymentDetails{}, err
}
Expand Down Expand Up @@ -249,12 +249,12 @@ func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
}

savedOwnerToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), ownerTokenParameters, txArgs.From.Hex(),
api.s.TemporaryOwnerContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.OwnerLevel)
api.s.TemporaryOwnerContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.OwnerLevel, tx.Hash().Hex())
if err != nil {
return DeploymentDetails{}, err
}
savedMasterToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), masterTokenParameters, txArgs.From.Hex(),
api.s.TemporaryMasterContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.MasterLevel)
api.s.TemporaryMasterContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.MasterLevel, tx.Hash().Hex())
if err != nil {
return DeploymentDetails{}, err
}
Expand All @@ -266,6 +266,11 @@ func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
MasterToken: savedMasterToken}, nil
}

// recovery function which starts transaction tracking again
func (api *API) ReTrackOwnerTokenDeploymentTransaction(ctx context.Context, chainID uint64, contractAddress string) error {
return api.s.ReTrackOwnerTokenDeploymentTransaction(ctx, chainID, contractAddress)
}

func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {

err := deploymentParameters.Validate(true)
Expand Down Expand Up @@ -307,7 +312,7 @@ func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentPara
}

savedCommunityToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), deploymentParameters, txArgs.From.Hex(), address.Hex(),
protobuf.CommunityTokenType_ERC20, token.CommunityLevel)
protobuf.CommunityTokenType_ERC20, token.CommunityLevel, tx.Hash().Hex())
if err != nil {
return DeploymentDetails{}, err
}
Expand Down
67 changes: 64 additions & 3 deletions services/communitytokens/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"math/big"
"strings"

"github.com/pkg/errors"

Expand Down Expand Up @@ -512,7 +513,7 @@ func (s *Service) maxSupply(ctx context.Context, chainID uint64, contractAddress
}

func (s *Service) CreateCommunityTokenAndSave(chainID int, deploymentParameters DeploymentParameters,
deployerAddress string, contractAddress string, tokenType protobuf.CommunityTokenType, privilegesLevel token.PrivilegesLevel) (*token.CommunityToken, error) {
deployerAddress string, contractAddress string, tokenType protobuf.CommunityTokenType, privilegesLevel token.PrivilegesLevel, transactionHash string) (*token.CommunityToken, error) {

tokenToSave := &token.CommunityToken{
TokenType: tokenType,
Expand All @@ -531,17 +532,32 @@ func (s *Service) CreateCommunityTokenAndSave(chainID int, deploymentParameters
Deployer: deployerAddress,
PrivilegesLevel: privilegesLevel,
Base64Image: deploymentParameters.Base64Image,
TransactionHash: transactionHash,
}

return s.Messenger.SaveCommunityToken(tokenToSave, deploymentParameters.CroppedImage)
}

const (
MasterSuffix = "-master"
OwnerSuffix = "-owner"
)

func (s *Service) TemporaryMasterContractAddress(hash string) string {
return hash + "-master"
return hash + MasterSuffix
}

func (s *Service) TemporaryOwnerContractAddress(hash string) string {
return hash + "-owner"
return hash + OwnerSuffix
}

func (s *Service) HashFromTemporaryContractAddress(address string) string {
if strings.HasSuffix(address, OwnerSuffix) {
return strings.TrimSuffix(address, OwnerSuffix)
} else if strings.HasSuffix(address, MasterSuffix) {
return strings.TrimSuffix(address, MasterSuffix)
}
return ""
}

func (s *Service) GetMasterTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
Expand Down Expand Up @@ -605,3 +621,48 @@ func (s *Service) GetOwnerTokenContractAddressFromHash(ctx context.Context, chai
}
return "", fmt.Errorf("can't find owner token address in transaction: %v", txHash)
}

func (s *Service) ReTrackOwnerTokenDeploymentTransaction(ctx context.Context, chainID uint64, contractAddress string) error {
communityToken, err := s.Messenger.GetCommunityTokenByChainAndAddress(int(chainID), contractAddress)
if err != nil {
return err
}
if communityToken == nil {
return fmt.Errorf("can't find token with address %v on chain %v", contractAddress, chainID)
}
if communityToken.DeployState != token.InProgress {
return fmt.Errorf("token with address %v on chain %v is not in progress", contractAddress, chainID)
}

hashString := communityToken.TransactionHash
if hashString == "" && (communityToken.PrivilegesLevel == token.OwnerLevel || communityToken.PrivilegesLevel == token.MasterLevel) {
hashString = s.HashFromTemporaryContractAddress(communityToken.Address)
}

if hashString == "" {
return fmt.Errorf("can't find transaction hash for token with address %v on chain %v", contractAddress, chainID)
}

transactionType := transactions.DeployCommunityToken
if communityToken.PrivilegesLevel == token.OwnerLevel || communityToken.PrivilegesLevel == token.MasterLevel {
transactionType = transactions.DeployOwnerToken
}

_, err = s.pendingTracker.GetPendingEntry(wcommon.ChainID(chainID), common.HexToHash(hashString))
if errors.Is(err, sql.ErrNoRows) {
// start only if no pending transaction in database
err = s.pendingTracker.TrackPendingTransaction(
wcommon.ChainID(chainID),
common.HexToHash(hashString),
common.HexToAddress(communityToken.Deployer),
common.Address{},
transactionType,
transactions.Keep,
"",
)
log.Debug("retracking pending transaction with hashId ", hashString)
} else {
log.Debug("pending transaction with hashId is already tracked ", hashString)
}
return err
}

0 comments on commit ad9032d

Please sign in to comment.