feat_: Move community tokens transaction listening to status-go
Use EventWatcher to catch wallet events. Handling all community tokens wallet events in communitytokens service (database and messenger operations). Adding new signal to nim: CommunityTokenTransactionSignal, which is emitted everytime when the event is received. Issue #4351
This commit is contained in:
parent
00ee631a22
commit
574450289c
|
@ -2366,6 +2366,7 @@ func (b *GethStatusBackend) injectAccountsIntoWakuService(w types.WakuKeyManager
|
|||
}
|
||||
b.statusNode.ChatService(accDB).Init(messenger)
|
||||
b.statusNode.EnsService().Init(messenger.SyncEnsNamesWithDispatchMessage)
|
||||
b.statusNode.CommunityTokensService().Init(messenger)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -487,7 +487,7 @@ func (b *StatusNode) pendingTrackerService(walletFeed *event.Feed) *transactions
|
|||
|
||||
func (b *StatusNode) CommunityTokensService() *communitytokens.Service {
|
||||
if b.communityTokensSrvc == nil {
|
||||
b.communityTokensSrvc = communitytokens.NewService(b.rpcClient, b.gethAccountManager, b.pendingTracker, b.config, b.appDB)
|
||||
b.communityTokensSrvc = communitytokens.NewService(b.rpcClient, b.gethAccountManager, b.pendingTracker, b.config, b.appDB, &b.walletFeed)
|
||||
}
|
||||
return b.communityTokensSrvc
|
||||
}
|
||||
|
|
|
@ -42,12 +42,12 @@ import (
|
|||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/requests"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
walletcommon "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/thirdparty"
|
||||
"github.com/status-im/status-go/services/wallet/token"
|
||||
"github.com/status-im/status-go/signal"
|
||||
"github.com/status-im/status-go/transactions"
|
||||
)
|
||||
|
||||
var defaultAnnounceList = [][]string{
|
||||
|
@ -102,7 +102,7 @@ type Manager struct {
|
|||
torrentConfig *params.TorrentConfig
|
||||
torrentClient *torrent.Client
|
||||
walletConfig *params.WalletConfig
|
||||
communityTokensService communitytokens.ServiceInterface
|
||||
communityTokensService CommunityTokensServiceInterface
|
||||
historyArchiveTasksWaitGroup sync.WaitGroup
|
||||
historyArchiveTasks sync.Map // stores `chan struct{}`
|
||||
membersReevaluationTasks sync.Map // stores `membersReevaluationTask`
|
||||
|
@ -190,7 +190,7 @@ type managerOptions struct {
|
|||
tokenManager TokenManager
|
||||
collectiblesManager CollectiblesManager
|
||||
walletConfig *params.WalletConfig
|
||||
communityTokensService communitytokens.ServiceInterface
|
||||
communityTokensService CommunityTokensServiceInterface
|
||||
permissionChecker PermissionChecker
|
||||
|
||||
// allowForcingCommunityMembersReevaluation indicates whether we should allow forcing community members reevaluation.
|
||||
|
@ -205,6 +205,26 @@ type TokenManager interface {
|
|||
GetAllChainIDs() ([]uint64, error)
|
||||
}
|
||||
|
||||
type CollectibleContractData struct {
|
||||
TotalSupply *bigint.BigInt
|
||||
Transferable bool
|
||||
RemoteBurnable bool
|
||||
InfiniteSupply bool
|
||||
}
|
||||
|
||||
type AssetContractData struct {
|
||||
TotalSupply *bigint.BigInt
|
||||
InfiniteSupply bool
|
||||
}
|
||||
|
||||
type CommunityTokensServiceInterface interface {
|
||||
GetCollectibleContractData(chainID uint64, contractAddress string) (*CollectibleContractData, error)
|
||||
SetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, newSignerPubKey string) (string, error)
|
||||
GetAssetContractData(chainID uint64, contractAddress string) (*AssetContractData, error)
|
||||
SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error)
|
||||
DeploymentSignatureDigest(chainID uint64, addressFrom string, communityID string) ([]byte, error)
|
||||
}
|
||||
|
||||
type DefaultTokenManager struct {
|
||||
tokenManager *token.Manager
|
||||
}
|
||||
|
@ -286,7 +306,7 @@ func WithWalletConfig(walletConfig *params.WalletConfig) ManagerOption {
|
|||
}
|
||||
}
|
||||
|
||||
func WithCommunityTokensService(communityTokensService communitytokens.ServiceInterface) ManagerOption {
|
||||
func WithCommunityTokensService(communityTokensService CommunityTokensServiceInterface) ManagerOption {
|
||||
return func(opts *managerOptions) {
|
||||
opts.communityTokensService = communityTokensService
|
||||
}
|
||||
|
@ -4747,6 +4767,10 @@ func (m *Manager) GetCommunityToken(communityID string, chainID int, address str
|
|||
return m.persistence.GetCommunityToken(communityID, chainID, address)
|
||||
}
|
||||
|
||||
func (m *Manager) GetCommunityTokenByChainAndAddress(chainID int, address string) (*community_token.CommunityToken, error) {
|
||||
return m.persistence.GetCommunityTokenByChainAndAddress(chainID, address)
|
||||
}
|
||||
|
||||
func (m *Manager) GetCommunityTokens(communityID string) ([]*community_token.CommunityToken, error) {
|
||||
return m.persistence.GetCommunityTokens(communityID)
|
||||
}
|
||||
|
|
|
@ -1276,6 +1276,29 @@ func (p *Persistence) GetCommunityToken(communityID string, chainID int, address
|
|||
return &token, nil
|
||||
}
|
||||
|
||||
func (p *Persistence) GetCommunityTokenByChainAndAddress(chainID int, address string) (*token.CommunityToken, error) {
|
||||
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
|
||||
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)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
supplyBigInt, ok := new(big.Int).SetString(supplyStr, 10)
|
||||
if ok {
|
||||
token.Supply = &bigint.BigInt{Int: supplyBigInt}
|
||||
} else {
|
||||
token.Supply = &bigint.BigInt{Int: big.NewInt(0)}
|
||||
}
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
func (p *Persistence) getCommunityTokensInternal(rows *sql.Rows) ([]*token.CommunityToken, error) {
|
||||
tokens := []*token.CommunityToken{}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/requests"
|
||||
"github.com/status-im/status-go/protocol/tt"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
)
|
||||
|
||||
|
@ -2061,7 +2060,7 @@ func testEventSenderAddTokenMasterAndOwnerToken(base CommunityEventsTestsInterfa
|
|||
}
|
||||
|
||||
func addCommunityTokenToCommunityTokensService(base CommunityEventsTestsInterface, token *token.CommunityToken) {
|
||||
data := &communitytokens.CollectibleContractData{
|
||||
data := &communities.CollectibleContractData{
|
||||
TotalSupply: token.Supply,
|
||||
Transferable: token.Transferable,
|
||||
RemoteBurnable: token.RemoteSelfDestruct,
|
||||
|
|
|
@ -24,7 +24,6 @@ import (
|
|||
"github.com/status-im/status-go/protocol/communities/token"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/requests"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
walletToken "github.com/status-im/status-go/services/wallet/token"
|
||||
"github.com/status-im/status-go/transactions"
|
||||
)
|
||||
|
@ -74,8 +73,8 @@ func (m *TokenManagerMock) FindOrCreateTokenByAddress(ctx context.Context, chain
|
|||
}
|
||||
|
||||
type CollectiblesServiceMock struct {
|
||||
Collectibles map[uint64]map[string]*communitytokens.CollectibleContractData
|
||||
Assets map[uint64]map[string]*communitytokens.AssetContractData
|
||||
Collectibles map[uint64]map[string]*communities.CollectibleContractData
|
||||
Assets map[uint64]map[string]*communities.AssetContractData
|
||||
Signers map[string]string
|
||||
}
|
||||
|
||||
|
@ -90,7 +89,7 @@ func (c *CollectiblesServiceMock) SetSignerPubKey(ctx context.Context, chainID u
|
|||
return "", nil
|
||||
}
|
||||
|
||||
func (c *CollectiblesServiceMock) GetCollectibleContractData(chainID uint64, contractAddress string) (*communitytokens.CollectibleContractData, error) {
|
||||
func (c *CollectiblesServiceMock) GetCollectibleContractData(chainID uint64, contractAddress string) (*communities.CollectibleContractData, error) {
|
||||
collectibleContractData, dataExists := c.Collectibles[chainID][contractAddress]
|
||||
if dataExists {
|
||||
return collectibleContractData, nil
|
||||
|
@ -98,7 +97,7 @@ func (c *CollectiblesServiceMock) GetCollectibleContractData(chainID uint64, con
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *CollectiblesServiceMock) GetAssetContractData(chainID uint64, contractAddress string) (*communitytokens.AssetContractData, error) {
|
||||
func (c *CollectiblesServiceMock) GetAssetContractData(chainID uint64, contractAddress string) (*communities.AssetContractData, error) {
|
||||
assetsContractData, dataExists := c.Assets[chainID][contractAddress]
|
||||
if dataExists {
|
||||
return assetsContractData, nil
|
||||
|
@ -106,22 +105,22 @@ func (c *CollectiblesServiceMock) GetAssetContractData(chainID uint64, contractA
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *CollectiblesServiceMock) SetMockCollectibleContractData(chainID uint64, contractAddress string, collectible *communitytokens.CollectibleContractData) {
|
||||
func (c *CollectiblesServiceMock) SetMockCollectibleContractData(chainID uint64, contractAddress string, collectible *communities.CollectibleContractData) {
|
||||
if c.Collectibles == nil {
|
||||
c.Collectibles = make(map[uint64]map[string]*communitytokens.CollectibleContractData)
|
||||
c.Collectibles = make(map[uint64]map[string]*communities.CollectibleContractData)
|
||||
}
|
||||
if _, ok := c.Collectibles[chainID]; !ok {
|
||||
c.Collectibles[chainID] = make(map[string]*communitytokens.CollectibleContractData)
|
||||
c.Collectibles[chainID] = make(map[string]*communities.CollectibleContractData)
|
||||
}
|
||||
c.Collectibles[chainID][contractAddress] = collectible
|
||||
}
|
||||
|
||||
func (c *CollectiblesServiceMock) SetMockCommunityTokenData(token *token.CommunityToken) {
|
||||
if c.Collectibles == nil {
|
||||
c.Collectibles = make(map[uint64]map[string]*communitytokens.CollectibleContractData)
|
||||
c.Collectibles = make(map[uint64]map[string]*communities.CollectibleContractData)
|
||||
}
|
||||
|
||||
data := &communitytokens.CollectibleContractData{
|
||||
data := &communities.CollectibleContractData{
|
||||
TotalSupply: token.Supply,
|
||||
Transferable: token.Transferable,
|
||||
RemoteBurnable: token.RemoteSelfDestruct,
|
||||
|
@ -138,11 +137,11 @@ func (c *CollectiblesServiceMock) SafeGetSignerPubKey(ctx context.Context, chain
|
|||
return c.Signers[communityID], nil
|
||||
}
|
||||
|
||||
func (c *CollectiblesServiceMock) SetMockAssetContractData(chainID uint64, contractAddress string, assetData *communitytokens.AssetContractData) {
|
||||
func (c *CollectiblesServiceMock) SetMockAssetContractData(chainID uint64, contractAddress string, assetData *communities.AssetContractData) {
|
||||
if c.Assets == nil {
|
||||
c.Assets = make(map[uint64]map[string]*communitytokens.AssetContractData)
|
||||
c.Assets = make(map[uint64]map[string]*communities.AssetContractData)
|
||||
}
|
||||
c.Assets[chainID] = make(map[string]*communitytokens.AssetContractData)
|
||||
c.Assets[chainID] = make(map[string]*communities.AssetContractData)
|
||||
c.Assets[chainID][contractAddress] = assetData
|
||||
}
|
||||
|
||||
|
@ -159,7 +158,7 @@ type testCommunitiesMessengerConfig struct {
|
|||
password string
|
||||
walletAddresses []string
|
||||
mockedBalances *map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
|
||||
collectiblesService communitytokens.ServiceInterface
|
||||
collectiblesService communities.CommunityTokensServiceInterface
|
||||
}
|
||||
|
||||
func (tcmc *testCommunitiesMessengerConfig) complete() error {
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/requests"
|
||||
"github.com/status-im/status-go/protocol/tt"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
@ -182,7 +181,7 @@ func (s *MessengerCommunitiesSignersSuite) TestControlNodeUpdateSigner() {
|
|||
// update mock - the signer for the community returned by the contracts should be john
|
||||
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.john.identity.PublicKey))
|
||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
|
||||
// bob accepts community update
|
||||
_, err = WaitOnSignaledMessengerResponse(
|
||||
|
@ -377,7 +376,7 @@ func (s *MessengerCommunitiesSignersSuite) TestAutoAcceptOnOwnershipChangeReques
|
|||
// set john as contract owner
|
||||
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.john.identity.PublicKey))
|
||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
|
||||
hasTokenPermission := func(r *MessengerResponse) bool {
|
||||
return len(r.Communities()) > 0 && r.Communities()[0].HasTokenPermissions()
|
||||
|
@ -515,7 +514,7 @@ func (s *MessengerCommunitiesSignersSuite) TestNewOwnerAcceptRequestToJoin() {
|
|||
// update mock - the signer for the community returned by the contracts should be john
|
||||
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.john.identity.PublicKey))
|
||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
|
||||
// alice accepts community update
|
||||
_, err = WaitOnSignaledMessengerResponse(
|
||||
|
|
|
@ -62,7 +62,6 @@ import (
|
|||
"github.com/status-im/status-go/protocol/verification"
|
||||
"github.com/status-im/status-go/server"
|
||||
"github.com/status-im/status-go/services/browsers"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
ensservice "github.com/status-im/status-go/services/ens"
|
||||
"github.com/status-im/status-go/services/ext/mailservers"
|
||||
localnotifications "github.com/status-im/status-go/services/local-notifications"
|
||||
|
@ -174,7 +173,7 @@ type Messenger struct {
|
|||
// flag to enable backedup messages processing, false by default
|
||||
processBackedupMessages bool
|
||||
|
||||
communityTokensService communitytokens.ServiceInterface
|
||||
communityTokensService communities.CommunityTokensServiceInterface
|
||||
|
||||
// used to track dispatched messages
|
||||
dispatchMessageTestCallback func(common.RawMessage)
|
||||
|
|
|
@ -4221,6 +4221,10 @@ func (m *Messenger) GetCommunityToken(communityID string, chainID int, address s
|
|||
return m.communitiesManager.GetCommunityToken(communityID, chainID, address)
|
||||
}
|
||||
|
||||
func (m *Messenger) GetCommunityTokenByChainAndAddress(chainID int, address string) (*token.CommunityToken, error) {
|
||||
return m.communitiesManager.GetCommunityTokenByChainAndAddress(chainID, address)
|
||||
}
|
||||
|
||||
func (m *Messenger) GetCommunityTokens(communityID string) ([]*token.CommunityToken, error) {
|
||||
return m.communitiesManager.GetCommunityTokens(communityID)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/status-im/status-go/rpc"
|
||||
"github.com/status-im/status-go/server"
|
||||
"github.com/status-im/status-go/services/browsers"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
"github.com/status-im/status-go/wakuv2"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
@ -90,7 +89,7 @@ type config struct {
|
|||
torrentConfig *params.TorrentConfig
|
||||
walletConfig *params.WalletConfig
|
||||
walletService *wallet.Service
|
||||
communityTokensService communitytokens.ServiceInterface
|
||||
communityTokensService communities.CommunityTokensServiceInterface
|
||||
httpServer *server.MediaServer
|
||||
rpcClient *rpc.Client
|
||||
tokenManager communities.TokenManager
|
||||
|
@ -379,7 +378,7 @@ func WithWalletService(s *wallet.Service) Option {
|
|||
}
|
||||
}
|
||||
|
||||
func WithCommunityTokensService(s communitytokens.ServiceInterface) Option {
|
||||
func WithCommunityTokensService(s communities.CommunityTokensServiceInterface) Option {
|
||||
return func(c *config) error {
|
||||
c.communityTokensService = s
|
||||
return nil
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"github.com/status-im/status-go/protocol/requests"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
"github.com/status-im/status-go/protocol/tt"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
mailserversDB "github.com/status-im/status-go/services/mailservers"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
"github.com/status-im/status-go/t/helpers"
|
||||
|
@ -1042,7 +1041,7 @@ func (s *MessengerStoreNodeRequestSuite) TestFetchRealCommunity() {
|
|||
for _, communityToken := range communityTokens {
|
||||
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(communityIDBytes, ownerPublicKey)
|
||||
s.collectiblesServiceMock.SetMockCollectibleContractData(communityToken.ChainID, communityToken.ContractAddress,
|
||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
}
|
||||
|
||||
results := map[string]singleResult{}
|
||||
|
@ -1205,7 +1204,7 @@ func (s *MessengerStoreNodeRequestSuite) TestFetchingCommunityWithOwnerToken() {
|
|||
// update mock - the signer for the community returned by the contracts should be owner
|
||||
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.owner.identity.PublicKey))
|
||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||
|
||||
community, err = s.owner.communitiesManager.GetByID(community.ID())
|
||||
s.Require().NoError(err)
|
||||
|
|
|
@ -2,11 +2,12 @@ package communitytokens
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
|
@ -19,6 +20,9 @@ import (
|
|||
"github.com/status-im/status-go/contracts/community-tokens/ownertoken"
|
||||
communityownertokenregistry "github.com/status-im/status-go/contracts/community-tokens/registry"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/images"
|
||||
"github.com/status-im/status-go/protocol/communities/token"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/services/utils"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
|
@ -37,22 +41,30 @@ type API struct {
|
|||
}
|
||||
|
||||
type DeploymentDetails struct {
|
||||
ContractAddress string `json:"contractAddress"`
|
||||
TransactionHash string `json:"transactionHash"`
|
||||
ContractAddress string `json:"contractAddress"`
|
||||
TransactionHash string `json:"transactionHash"`
|
||||
CommunityToken *token.CommunityToken `json:"communityToken"`
|
||||
OwnerToken *token.CommunityToken `json:"ownerToken"`
|
||||
MasterToken *token.CommunityToken `json:"masterToken"`
|
||||
}
|
||||
|
||||
const maxSupply = 999999999
|
||||
|
||||
type DeploymentParameters struct {
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Supply *bigint.BigInt `json:"supply"`
|
||||
InfiniteSupply bool `json:"infiniteSupply"`
|
||||
Transferable bool `json:"transferable"`
|
||||
RemoteSelfDestruct bool `json:"remoteSelfDestruct"`
|
||||
TokenURI string `json:"tokenUri"`
|
||||
OwnerTokenAddress string `json:"ownerTokenAddress"`
|
||||
MasterTokenAddress string `json:"masterTokenAddress"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Supply *bigint.BigInt `json:"supply"`
|
||||
InfiniteSupply bool `json:"infiniteSupply"`
|
||||
Transferable bool `json:"transferable"`
|
||||
RemoteSelfDestruct bool `json:"remoteSelfDestruct"`
|
||||
TokenURI string `json:"tokenUri"`
|
||||
OwnerTokenAddress string `json:"ownerTokenAddress"`
|
||||
MasterTokenAddress string `json:"masterTokenAddress"`
|
||||
CommunityID string `json:"communityId"`
|
||||
Description string `json:"description"`
|
||||
CroppedImage *images.CroppedImage `json:"croppedImage,omitempty"` // for community tokens
|
||||
Base64Image string `json:"base64image"` // for owner & master tokens
|
||||
Decimals int `json:"decimals"`
|
||||
}
|
||||
|
||||
func (d *DeploymentParameters) GetSupply() *big.Int {
|
||||
|
@ -92,12 +104,10 @@ func (d *DeploymentParameters) Validate(isAsset bool) error {
|
|||
}
|
||||
|
||||
func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deploymentParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||
|
||||
err := deploymentParameters.Validate(false)
|
||||
if err != nil {
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
||||
|
||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
||||
|
@ -105,7 +115,6 @@ func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deployme
|
|||
log.Error(err.Error())
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
address, tx, _, err := collectibles.DeployCollectibles(transactOpts, ethClient, deploymentParameters.Name,
|
||||
deploymentParameters.Symbol, deploymentParameters.GetSupply(),
|
||||
deploymentParameters.RemoteSelfDestruct, deploymentParameters.Transferable,
|
||||
|
@ -120,15 +129,26 @@ func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deployme
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
address,
|
||||
transactions.DeployCommunityToken,
|
||||
transactions.AutoDelete,
|
||||
transactions.Keep,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
return DeploymentDetails{address.Hex(), tx.Hash().Hex()}, nil
|
||||
savedCommunityToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), deploymentParameters, txArgs.From.Hex(), address.Hex(),
|
||||
protobuf.CommunityTokenType_ERC721, token.CommunityLevel)
|
||||
if err != nil {
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
return DeploymentDetails{
|
||||
ContractAddress: address.Hex(),
|
||||
TransactionHash: tx.Hash().Hex(),
|
||||
CommunityToken: savedCommunityToken}, nil
|
||||
}
|
||||
|
||||
func decodeSignature(sig []byte) (r [32]byte, s [32]byte, v uint8, err error) {
|
||||
|
@ -162,8 +182,7 @@ func prepareDeploymentSignatureStruct(signature string, communityID string, addr
|
|||
|
||||
func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
|
||||
ownerTokenParameters DeploymentParameters, masterTokenParameters DeploymentParameters,
|
||||
signature string, communityID string, signerPubKey string,
|
||||
txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||
signerPubKey string, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||
err := ownerTokenParameters.Validate(false)
|
||||
if err != nil {
|
||||
return DeploymentDetails{}, err
|
||||
|
@ -197,7 +216,12 @@ func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
|
|||
BaseURI: masterTokenParameters.TokenURI,
|
||||
}
|
||||
|
||||
communitySignature, err := prepareDeploymentSignatureStruct(signature, communityID, common.Address(txArgs.From))
|
||||
signature, err := api.s.Messenger.CreateCommunityTokenDeploymentSignature(context.Background(), chainID, txArgs.From.Hex(), ownerTokenParameters.CommunityID)
|
||||
if err != nil {
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
communitySignature, err := prepareDeploymentSignatureStruct(types.HexBytes(signature).String(), ownerTokenParameters.CommunityID, common.Address(txArgs.From))
|
||||
if err != nil {
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
@ -211,81 +235,38 @@ func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
|
|||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
log.Debug("Contract deployed hash:", tx.Hash().String())
|
||||
|
||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
||||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
common.Address{},
|
||||
transactions.DeployOwnerToken,
|
||||
transactions.AutoDelete,
|
||||
transactions.Keep,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
return DeploymentDetails{"", tx.Hash().Hex()}, nil
|
||||
}
|
||||
|
||||
func (api *API) GetMasterTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
|
||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
||||
savedOwnerToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), ownerTokenParameters, txArgs.From.Hex(),
|
||||
api.s.TemporaryOwnerContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.OwnerLevel)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
receipt, err := ethClient.TransactionReceipt(ctx, common.HexToHash(txHash))
|
||||
savedMasterToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), masterTokenParameters, txArgs.From.Hex(),
|
||||
api.s.TemporaryMasterContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.MasterLevel)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
deployerContractInst, err := api.NewCommunityTokenDeployerInstance(chainID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
logMasterTokenCreatedSig := []byte("DeployMasterToken(address)")
|
||||
logMasterTokenCreatedSigHash := crypto.Keccak256Hash(logMasterTokenCreatedSig)
|
||||
|
||||
for _, vLog := range receipt.Logs {
|
||||
if vLog.Topics[0].Hex() == logMasterTokenCreatedSigHash.Hex() {
|
||||
event, err := deployerContractInst.ParseDeployMasterToken(*vLog)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return event.Arg0.Hex(), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("can't find master token address in transaction: %v", txHash)
|
||||
}
|
||||
|
||||
func (api *API) GetOwnerTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
|
||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
receipt, err := ethClient.TransactionReceipt(ctx, common.HexToHash(txHash))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
deployerContractInst, err := api.NewCommunityTokenDeployerInstance(chainID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
logOwnerTokenCreatedSig := []byte("DeployOwnerToken(address)")
|
||||
logOwnerTokenCreatedSigHash := crypto.Keccak256Hash(logOwnerTokenCreatedSig)
|
||||
|
||||
for _, vLog := range receipt.Logs {
|
||||
if vLog.Topics[0].Hex() == logOwnerTokenCreatedSigHash.Hex() {
|
||||
event, err := deployerContractInst.ParseDeployOwnerToken(*vLog)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return event.Arg0.Hex(), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("can't find owner token address in transaction: %v", txHash)
|
||||
return DeploymentDetails{
|
||||
ContractAddress: "",
|
||||
TransactionHash: tx.Hash().Hex(),
|
||||
OwnerToken: savedOwnerToken,
|
||||
MasterToken: savedMasterToken}, nil
|
||||
}
|
||||
|
||||
func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||
|
@ -318,15 +299,26 @@ func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentPara
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
address,
|
||||
transactions.DeployCommunityToken,
|
||||
transactions.AutoDelete,
|
||||
transactions.Keep,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
return DeploymentDetails{address.Hex(), tx.Hash().Hex()}, nil
|
||||
savedCommunityToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), deploymentParameters, txArgs.From.Hex(), address.Hex(),
|
||||
protobuf.CommunityTokenType_ERC20, token.CommunityLevel)
|
||||
if err != nil {
|
||||
return DeploymentDetails{}, err
|
||||
}
|
||||
|
||||
return DeploymentDetails{
|
||||
ContractAddress: address.Hex(),
|
||||
TransactionHash: tx.Hash().Hex(),
|
||||
CommunityToken: savedCommunityToken}, nil
|
||||
}
|
||||
|
||||
// Returns gas units + 10%
|
||||
|
@ -403,7 +395,7 @@ func (api *API) DeployAssetsEstimate(ctx context.Context, chainID uint64, fromAd
|
|||
|
||||
func (api *API) DeployOwnerTokenEstimate(ctx context.Context, chainID uint64, fromAddress string,
|
||||
ownerTokenParameters DeploymentParameters, masterTokenParameters DeploymentParameters,
|
||||
signature string, communityID string, signerPubKey string) (uint64, error) {
|
||||
communityID string, signerPubKey string) (uint64, error) {
|
||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
|
@ -432,7 +424,12 @@ func (api *API) DeployOwnerTokenEstimate(ctx context.Context, chainID uint64, fr
|
|||
BaseURI: masterTokenParameters.TokenURI,
|
||||
}
|
||||
|
||||
communitySignature, err := prepareDeploymentSignatureStruct(signature, communityID, common.HexToAddress(fromAddress))
|
||||
signature, err := api.s.Messenger.CreateCommunityTokenDeploymentSignature(ctx, chainID, fromAddress, communityID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
communitySignature, err := prepareDeploymentSignatureStruct(types.HexBytes(signature).String(), communityID, common.HexToAddress(fromAddress))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -531,8 +528,10 @@ func (api *API) MintTokens(ctx context.Context, chainID uint64, contractAddress
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
common.HexToAddress(contractAddress),
|
||||
transactions.AirdropCommunityToken,
|
||||
transactions.AutoDelete,
|
||||
transactions.Keep,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
|
@ -614,7 +613,7 @@ func (api *API) RemoteDestructedAmount(ctx context.Context, chainID uint64, cont
|
|||
}
|
||||
|
||||
// This is only ERC721 function
|
||||
func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, tokenIds []*bigint.BigInt) (string, error) {
|
||||
func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, tokenIds []*bigint.BigInt, additionalData string) (string, error) {
|
||||
err := api.validateTokens(tokenIds)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -641,8 +640,10 @@ func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
common.HexToAddress(contractAddress),
|
||||
transactions.RemoteDestructCollectible,
|
||||
transactions.AutoDelete,
|
||||
transactions.Keep,
|
||||
additionalData,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
|
@ -730,42 +731,8 @@ func (api *API) remainingAssetsSupply(ctx context.Context, chainID uint64, contr
|
|||
return &bigint.BigInt{Int: res}, nil
|
||||
}
|
||||
|
||||
func (api *API) maxSupplyCollectibles(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||
contractInst, err := api.NewCollectiblesInstance(chainID, contractAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return contractInst.MaxSupply(callOpts)
|
||||
}
|
||||
|
||||
func (api *API) maxSupplyAssets(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||
contractInst, err := api.NewAssetsInstance(chainID, contractAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return contractInst.MaxSupply(callOpts)
|
||||
}
|
||||
|
||||
func (api *API) maxSupply(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||
tokenType, err := api.s.db.GetTokenType(chainID, contractAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch tokenType {
|
||||
case protobuf.CommunityTokenType_ERC721:
|
||||
return api.maxSupplyCollectibles(ctx, chainID, contractAddress)
|
||||
case protobuf.CommunityTokenType_ERC20:
|
||||
return api.maxSupplyAssets(ctx, chainID, contractAddress)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown token type: %v", tokenType)
|
||||
}
|
||||
}
|
||||
|
||||
func (api *API) prepareNewMaxSupply(ctx context.Context, chainID uint64, contractAddress string, burnAmount *bigint.BigInt) (*big.Int, error) {
|
||||
maxSupply, err := api.maxSupply(ctx, chainID, contractAddress)
|
||||
maxSupply, err := api.s.maxSupply(ctx, chainID, contractAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -801,8 +768,10 @@ func (api *API) Burn(ctx context.Context, chainID uint64, contractAddress string
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
common.HexToAddress(contractAddress),
|
||||
transactions.BurnCommunityToken,
|
||||
transactions.AutoDelete,
|
||||
transactions.Keep,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
|
|
|
@ -19,37 +19,37 @@ func TestDeploymentParameters(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "emptyName",
|
||||
parameters: DeploymentParameters{"", "SYMBOL", &bigint.BigInt{Int: big.NewInt(int64(123))}, false, false, false, "", "", ""},
|
||||
parameters: DeploymentParameters{"", "SYMBOL", &bigint.BigInt{Int: big.NewInt(int64(123))}, false, false, false, "", "", "", "", "", nil, "", 0},
|
||||
isError: true,
|
||||
},
|
||||
{
|
||||
name: "emptySymbol",
|
||||
parameters: DeploymentParameters{"NAME", "", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, "", "", ""},
|
||||
parameters: DeploymentParameters{"NAME", "", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, "", "", "", "", "", nil, "", 0},
|
||||
isError: true,
|
||||
},
|
||||
{
|
||||
name: "negativeSupply",
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, false, false, false, "", "", ""},
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, false, false, false, "", "", "", "", "", nil, "", 0},
|
||||
isError: true,
|
||||
},
|
||||
{
|
||||
name: "zeroSupply",
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(0)}, false, false, false, "", "", ""},
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(0)}, false, false, false, "", "", "", "", "", nil, "", 0},
|
||||
isError: false,
|
||||
},
|
||||
{
|
||||
name: "negativeSupplyAndInfinite",
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, true, false, false, "", "", ""},
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, true, false, false, "", "", "", "", "", nil, "", 0},
|
||||
isError: false,
|
||||
},
|
||||
{
|
||||
name: "supplyGreaterThanMax",
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply + 1)}, false, false, false, "", "", ""},
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply + 1)}, false, false, false, "", "", "", "", "", nil, "", 0},
|
||||
isError: true,
|
||||
},
|
||||
{
|
||||
name: "supplyIsMax",
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply)}, false, false, false, "", "", ""},
|
||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply)}, false, false, false, "", "", "", "", "", nil, "", 0},
|
||||
isError: false,
|
||||
},
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ func TestDeploymentParameters(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
notInfiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, "", "", ""}
|
||||
notInfiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, "", "", "", "", "", nil, "", 0}
|
||||
requiredSupply := big.NewInt(123)
|
||||
require.Equal(t, notInfiniteSupplyParams.GetSupply(), requiredSupply)
|
||||
infiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, true, false, false, "", "", ""}
|
||||
infiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, true, false, false, "", "", "", "", "", nil, "", 0}
|
||||
requiredSupply = infiniteSupplyParams.GetInfiniteSupply()
|
||||
require.Equal(t, infiniteSupplyParams.GetSupply(), requiredSupply)
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package communitytokens
|
||||
|
||||
import "github.com/status-im/status-go/services/wallet/bigint"
|
||||
|
||||
type AssetContractData struct {
|
||||
TotalSupply *bigint.BigInt
|
||||
InfiniteSupply bool
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package communitytokens
|
||||
|
||||
import "github.com/status-im/status-go/services/wallet/bigint"
|
||||
|
||||
type CollectibleContractData struct {
|
||||
TotalSupply *bigint.BigInt
|
||||
Transferable bool
|
||||
RemoteBurnable bool
|
||||
InfiniteSupply bool
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package communitytokens
|
||||
package communitytokensdatabase
|
||||
|
||||
import (
|
||||
"database/sql"
|
|
@ -1,4 +1,4 @@
|
|||
package communitytokens
|
||||
package communitytokensdatabase
|
||||
|
||||
import (
|
||||
"database/sql"
|
|
@ -13,6 +13,7 @@ import (
|
|||
communitytokendeployer "github.com/status-im/status-go/contracts/community-tokens/deployer"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/protocol/communities"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
)
|
||||
|
@ -71,7 +72,7 @@ func (m *Manager) GetAssetContractInstance(chainID uint64, contractAddress strin
|
|||
return contractInst, nil
|
||||
}
|
||||
|
||||
func (m *Manager) GetCollectibleContractData(chainID uint64, contractAddress string) (*CollectibleContractData, error) {
|
||||
func (m *Manager) GetCollectibleContractData(chainID uint64, contractAddress string) (*communities.CollectibleContractData, error) {
|
||||
callOpts := &bind.CallOpts{Context: context.Background(), Pending: false}
|
||||
|
||||
contract, err := m.GetCollectiblesContractInstance(chainID, contractAddress)
|
||||
|
@ -91,7 +92,7 @@ func (m *Manager) GetCollectibleContractData(chainID uint64, contractAddress str
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &CollectibleContractData{
|
||||
return &communities.CollectibleContractData{
|
||||
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
||||
Transferable: transferable,
|
||||
RemoteBurnable: remoteBurnable,
|
||||
|
@ -99,7 +100,7 @@ func (m *Manager) GetCollectibleContractData(chainID uint64, contractAddress str
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (m *Manager) GetAssetContractData(chainID uint64, contractAddress string) (*AssetContractData, error) {
|
||||
func (m *Manager) GetAssetContractData(chainID uint64, contractAddress string) (*communities.AssetContractData, error) {
|
||||
callOpts := &bind.CallOpts{Context: context.Background(), Pending: false}
|
||||
contract, err := m.GetAssetContractInstance(chainID, contractAddress)
|
||||
if err != nil {
|
||||
|
@ -110,7 +111,7 @@ func (m *Manager) GetAssetContractData(chainID uint64, contractAddress string) (
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &AssetContractData{
|
||||
return &communities.AssetContractData{
|
||||
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
||||
InfiniteSupply: GetInfiniteSupply().Cmp(totalSupply) == 0,
|
||||
}, nil
|
||||
|
|
|
@ -3,49 +3,60 @@ package communitytokens
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
ethRpc "github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/status-im/status-go/account"
|
||||
"github.com/status-im/status-go/contracts/community-tokens/ownertoken"
|
||||
communityownertokenregistry "github.com/status-im/status-go/contracts/community-tokens/registry"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/params"
|
||||
"github.com/status-im/status-go/protocol"
|
||||
"github.com/status-im/status-go/protocol/communities"
|
||||
"github.com/status-im/status-go/protocol/communities/token"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
"github.com/status-im/status-go/services/communitytokens/communitytokensdatabase"
|
||||
"github.com/status-im/status-go/services/utils"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
wcommon "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||
"github.com/status-im/status-go/signal"
|
||||
"github.com/status-im/status-go/transactions"
|
||||
)
|
||||
|
||||
type ServiceInterface interface {
|
||||
GetCollectibleContractData(chainID uint64, contractAddress string) (*CollectibleContractData, error)
|
||||
SetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, newSignerPubKey string) (string, error)
|
||||
GetAssetContractData(chainID uint64, contractAddress string) (*AssetContractData, error)
|
||||
SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error)
|
||||
DeploymentSignatureDigest(chainID uint64, addressFrom string, communityID string) ([]byte, error)
|
||||
}
|
||||
|
||||
// Collectibles service
|
||||
type Service struct {
|
||||
manager *Manager
|
||||
accountsManager *account.GethManager
|
||||
pendingTracker *transactions.PendingTxTracker
|
||||
config *params.NodeConfig
|
||||
db *Database
|
||||
db *communitytokensdatabase.Database
|
||||
Messenger *protocol.Messenger
|
||||
walletFeed *event.Feed
|
||||
walletWatcher *walletevent.Watcher
|
||||
}
|
||||
|
||||
// Returns a new Collectibles Service.
|
||||
func NewService(rpcClient *rpc.Client, accountsManager *account.GethManager, pendingTracker *transactions.PendingTxTracker, config *params.NodeConfig, appDb *sql.DB) *Service {
|
||||
func NewService(rpcClient *rpc.Client, accountsManager *account.GethManager, pendingTracker *transactions.PendingTxTracker,
|
||||
config *params.NodeConfig, appDb *sql.DB, walletFeed *event.Feed) *Service {
|
||||
return &Service{
|
||||
manager: &Manager{rpcClient: rpcClient},
|
||||
accountsManager: accountsManager,
|
||||
pendingTracker: pendingTracker,
|
||||
config: config,
|
||||
db: NewCommunityTokensDatabase(appDb),
|
||||
db: communitytokensdatabase.NewCommunityTokensDatabase(appDb),
|
||||
walletFeed: walletFeed,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,14 +79,181 @@ func (s *Service) APIs() []ethRpc.API {
|
|||
|
||||
// Start is run when a service is started.
|
||||
func (s *Service) Start() error {
|
||||
|
||||
s.walletWatcher = walletevent.NewWatcher(s.walletFeed, s.handleWalletEvent)
|
||||
s.walletWatcher.Start()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) handleWalletEvent(event walletevent.Event) {
|
||||
if event.Type == transactions.EventPendingTransactionStatusChanged {
|
||||
var p transactions.StatusChangedPayload
|
||||
err := json.Unmarshal([]byte(event.Message), &p)
|
||||
if err != nil {
|
||||
log.Error(errors.Wrap(err, fmt.Sprintf("can't parse transaction message %v\n", event.Message)).Error())
|
||||
return
|
||||
}
|
||||
if p.Status == transactions.Pending {
|
||||
return
|
||||
}
|
||||
pendingTransaction, err := s.pendingTracker.GetPendingEntry(p.ChainID, p.Hash)
|
||||
if err != nil {
|
||||
log.Error(errors.Wrap(err, fmt.Sprintf("no pending transaction with hash %v on chain %v\n", p.Hash, p.ChainID)).Error())
|
||||
return
|
||||
}
|
||||
|
||||
var communityToken, ownerToken, masterToken *token.CommunityToken = &token.CommunityToken{}, &token.CommunityToken{}, &token.CommunityToken{}
|
||||
var tokenErr error
|
||||
switch pendingTransaction.Type {
|
||||
case transactions.DeployCommunityToken:
|
||||
communityToken, tokenErr = s.handleDeployCommunityToken(p.Status, pendingTransaction)
|
||||
case transactions.AirdropCommunityToken:
|
||||
communityToken, tokenErr = s.handleAirdropCommunityToken(p.Status, pendingTransaction)
|
||||
case transactions.RemoteDestructCollectible:
|
||||
communityToken, tokenErr = s.handleRemoteDestructCollectible(p.Status, pendingTransaction)
|
||||
case transactions.BurnCommunityToken:
|
||||
communityToken, tokenErr = s.handleBurnCommunityToken(p.Status, pendingTransaction)
|
||||
case transactions.DeployOwnerToken:
|
||||
ownerToken, masterToken, tokenErr = s.handleDeployOwnerToken(p.Status, pendingTransaction)
|
||||
case transactions.SetSignerPublicKey:
|
||||
communityToken, tokenErr = s.handleSetSignerPubKey(p.Status, pendingTransaction)
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
err = s.pendingTracker.Delete(context.Background(), p.ChainID, p.Hash)
|
||||
if err != nil {
|
||||
log.Error(errors.Wrap(err, fmt.Sprintf("can't delete pending transaction with hash %v on chain %v\n", p.Hash, p.ChainID)).Error())
|
||||
}
|
||||
|
||||
errorStr := ""
|
||||
if tokenErr != nil {
|
||||
errorStr = tokenErr.Error()
|
||||
}
|
||||
|
||||
signal.SendCommunityTokenTransactionStatusSignal(string(pendingTransaction.Type), p.Status == transactions.Success, pendingTransaction.Hash,
|
||||
communityToken, ownerToken, masterToken, errorStr)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) handleAirdropCommunityToken(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, error) {
|
||||
return s.Messenger.GetCommunityTokenByChainAndAddress(int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
||||
}
|
||||
|
||||
func (s *Service) handleRemoteDestructCollectible(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, error) {
|
||||
return s.Messenger.GetCommunityTokenByChainAndAddress(int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
||||
}
|
||||
|
||||
func (s *Service) handleBurnCommunityToken(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, error) {
|
||||
|
||||
if status == transactions.Success {
|
||||
// get new max supply and update database
|
||||
newMaxSupply, err := s.maxSupply(context.Background(), uint64(pendingTransaction.ChainID), pendingTransaction.To.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = s.Messenger.UpdateCommunityTokenSupply(int(pendingTransaction.ChainID), pendingTransaction.To.String(), &bigint.BigInt{Int: newMaxSupply})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return s.Messenger.GetCommunityTokenByChainAndAddress(int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
||||
}
|
||||
|
||||
func (s *Service) handleDeployOwnerToken(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, *token.CommunityToken, error) {
|
||||
newMasterAddress, err := s.GetMasterTokenContractAddressFromHash(context.Background(), uint64(pendingTransaction.ChainID), pendingTransaction.Hash.Hex())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
newOwnerAddress, err := s.GetOwnerTokenContractAddressFromHash(context.Background(), uint64(pendingTransaction.ChainID), pendingTransaction.Hash.Hex())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = s.Messenger.UpdateCommunityTokenAddress(int(pendingTransaction.ChainID), s.TemporaryOwnerContractAddress(pendingTransaction.Hash.Hex()), newOwnerAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = s.Messenger.UpdateCommunityTokenAddress(int(pendingTransaction.ChainID), s.TemporaryMasterContractAddress(pendingTransaction.Hash.Hex()), newMasterAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ownerToken, err := s.updateStateAndAddTokenToCommunityDescription(status, int(pendingTransaction.ChainID), newOwnerAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
masterToken, err := s.updateStateAndAddTokenToCommunityDescription(status, int(pendingTransaction.ChainID), newMasterAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return ownerToken, masterToken, nil
|
||||
}
|
||||
|
||||
func (s *Service) updateStateAndAddTokenToCommunityDescription(status string, chainID int, address string) (*token.CommunityToken, error) {
|
||||
tokenToUpdate, err := s.Messenger.GetCommunityTokenByChainAndAddress(chainID, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tokenToUpdate == nil {
|
||||
return nil, fmt.Errorf("token does not exist in database: chainID=%v, address=%v", chainID, address)
|
||||
}
|
||||
|
||||
if status == transactions.Success {
|
||||
err := s.Messenger.UpdateCommunityTokenState(chainID, address, token.Deployed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = s.Messenger.AddCommunityToken(tokenToUpdate.CommunityID, chainID, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
err := s.Messenger.UpdateCommunityTokenState(chainID, address, token.Failed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return s.Messenger.GetCommunityTokenByChainAndAddress(chainID, address)
|
||||
}
|
||||
|
||||
func (s *Service) handleDeployCommunityToken(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, error) {
|
||||
return s.updateStateAndAddTokenToCommunityDescription(status, int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
||||
}
|
||||
|
||||
func (s *Service) handleSetSignerPubKey(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, error) {
|
||||
|
||||
communityToken, err := s.Messenger.GetCommunityTokenByChainAndAddress(int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if communityToken == nil {
|
||||
return nil, fmt.Errorf("token does not exist in database: chainId=%v, address=%v", pendingTransaction.ChainID, pendingTransaction.To.String())
|
||||
}
|
||||
|
||||
if status == transactions.Success {
|
||||
_, err := s.Messenger.PromoteSelfToControlNode(types.FromHex(communityToken.CommunityID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return communityToken, err
|
||||
}
|
||||
|
||||
// Stop is run when a service is stopped.
|
||||
func (s *Service) Stop() error {
|
||||
s.walletWatcher.Stop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Init(messenger *protocol.Messenger) {
|
||||
s.Messenger = messenger
|
||||
}
|
||||
|
||||
func (s *Service) NewCommunityOwnerTokenRegistryInstance(chainID uint64, contractAddress string) (*communityownertokenregistry.CommunityOwnerTokenRegistry, error) {
|
||||
backend, err := s.manager.rpcClient.EthClient(chainID)
|
||||
if err != nil {
|
||||
|
@ -142,11 +320,11 @@ func (s *Service) SafeGetOwnerTokenAddress(ctx context.Context, chainID uint64,
|
|||
return ownerTokenAddress.Hex(), err
|
||||
}
|
||||
|
||||
func (s *Service) GetCollectibleContractData(chainID uint64, contractAddress string) (*CollectibleContractData, error) {
|
||||
func (s *Service) GetCollectibleContractData(chainID uint64, contractAddress string) (*communities.CollectibleContractData, error) {
|
||||
return s.manager.GetCollectibleContractData(chainID, contractAddress)
|
||||
}
|
||||
|
||||
func (s *Service) GetAssetContractData(chainID uint64, contractAddress string) (*AssetContractData, error) {
|
||||
func (s *Service) GetAssetContractData(chainID uint64, contractAddress string) (*communities.AssetContractData, error) {
|
||||
return s.manager.GetAssetContractData(chainID, contractAddress)
|
||||
}
|
||||
|
||||
|
@ -176,8 +354,10 @@ func (s *Service) SetSignerPubKey(ctx context.Context, chainID uint64, contractA
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
common.HexToAddress(contractAddress),
|
||||
transactions.SetSignerPublicKey,
|
||||
transactions.AutoDelete,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
|
@ -186,3 +366,132 @@ func (s *Service) SetSignerPubKey(ctx context.Context, chainID uint64, contractA
|
|||
|
||||
return tx.Hash().Hex(), nil
|
||||
}
|
||||
|
||||
func (s *Service) maxSupplyCollectibles(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||
contractInst, err := s.manager.NewCollectiblesInstance(chainID, contractAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return contractInst.MaxSupply(callOpts)
|
||||
}
|
||||
|
||||
func (s *Service) maxSupplyAssets(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||
contractInst, err := s.manager.NewAssetsInstance(chainID, contractAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return contractInst.MaxSupply(callOpts)
|
||||
}
|
||||
|
||||
func (s *Service) maxSupply(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||
tokenType, err := s.db.GetTokenType(chainID, contractAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch tokenType {
|
||||
case protobuf.CommunityTokenType_ERC721:
|
||||
return s.maxSupplyCollectibles(ctx, chainID, contractAddress)
|
||||
case protobuf.CommunityTokenType_ERC20:
|
||||
return s.maxSupplyAssets(ctx, chainID, contractAddress)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown token type: %v", tokenType)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) CreateCommunityTokenAndSave(chainID int, deploymentParameters DeploymentParameters,
|
||||
deployerAddress string, contractAddress string, tokenType protobuf.CommunityTokenType, privilegesLevel token.PrivilegesLevel) (*token.CommunityToken, error) {
|
||||
|
||||
tokenToSave := &token.CommunityToken{
|
||||
TokenType: tokenType,
|
||||
CommunityID: deploymentParameters.CommunityID,
|
||||
Address: contractAddress,
|
||||
Name: deploymentParameters.Name,
|
||||
Symbol: deploymentParameters.Symbol,
|
||||
Description: deploymentParameters.Description,
|
||||
Supply: &bigint.BigInt{Int: deploymentParameters.GetSupply()},
|
||||
InfiniteSupply: deploymentParameters.InfiniteSupply,
|
||||
Transferable: deploymentParameters.Transferable,
|
||||
RemoteSelfDestruct: deploymentParameters.RemoteSelfDestruct,
|
||||
ChainID: chainID,
|
||||
DeployState: token.InProgress,
|
||||
Decimals: deploymentParameters.Decimals,
|
||||
Deployer: deployerAddress,
|
||||
PrivilegesLevel: privilegesLevel,
|
||||
Base64Image: deploymentParameters.Base64Image,
|
||||
}
|
||||
|
||||
return s.Messenger.SaveCommunityToken(tokenToSave, deploymentParameters.CroppedImage)
|
||||
}
|
||||
|
||||
func (s *Service) TemporaryMasterContractAddress(hash string) string {
|
||||
return hash + "-master"
|
||||
}
|
||||
|
||||
func (s *Service) TemporaryOwnerContractAddress(hash string) string {
|
||||
return hash + "-owner"
|
||||
}
|
||||
|
||||
func (s *Service) GetMasterTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
|
||||
ethClient, err := s.manager.rpcClient.EthClient(chainID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
receipt, err := ethClient.TransactionReceipt(ctx, common.HexToHash(txHash))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
deployerContractInst, err := s.manager.NewCommunityTokenDeployerInstance(chainID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
logMasterTokenCreatedSig := []byte("DeployMasterToken(address)")
|
||||
logMasterTokenCreatedSigHash := crypto.Keccak256Hash(logMasterTokenCreatedSig)
|
||||
|
||||
for _, vLog := range receipt.Logs {
|
||||
if vLog.Topics[0].Hex() == logMasterTokenCreatedSigHash.Hex() {
|
||||
event, err := deployerContractInst.ParseDeployMasterToken(*vLog)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return event.Arg0.Hex(), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("can't find master token address in transaction: %v", txHash)
|
||||
}
|
||||
|
||||
func (s *Service) GetOwnerTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
|
||||
ethClient, err := s.manager.rpcClient.EthClient(chainID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
receipt, err := ethClient.TransactionReceipt(ctx, common.HexToHash(txHash))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
deployerContractInst, err := s.manager.NewCommunityTokenDeployerInstance(chainID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
logOwnerTokenCreatedSig := []byte("DeployOwnerToken(address)")
|
||||
logOwnerTokenCreatedSigHash := crypto.Keccak256Hash(logOwnerTokenCreatedSig)
|
||||
|
||||
for _, vLog := range receipt.Logs {
|
||||
if vLog.Topics[0].Hex() == logOwnerTokenCreatedSigHash.Hex() {
|
||||
event, err := deployerContractInst.ParseDeployOwnerToken(*vLog)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return event.Arg0.Hex(), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("can't find owner token address in transaction: %v", txHash)
|
||||
}
|
||||
|
|
|
@ -357,8 +357,10 @@ func (api *API) Release(ctx context.Context, chainID uint64, txArgs transactions
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
registryAddr,
|
||||
transactions.ReleaseENS,
|
||||
transactions.AutoDelete,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
|
@ -484,8 +486,10 @@ func (api *API) Register(ctx context.Context, chainID uint64, txArgs transaction
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
registryAddr,
|
||||
transactions.RegisterENS,
|
||||
transactions.AutoDelete,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
|
@ -600,8 +604,10 @@ func (api *API) SetPubKey(ctx context.Context, chainID uint64, txArgs transactio
|
|||
wcommon.ChainID(chainID),
|
||||
tx.Hash(),
|
||||
common.Address(txArgs.From),
|
||||
*resolverAddress,
|
||||
transactions.SetPubKey,
|
||||
transactions.AutoDelete,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("TrackPendingTransaction error", "error", err)
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
"github.com/status-im/status-go/rpc/network"
|
||||
"github.com/status-im/status-go/server"
|
||||
"github.com/status-im/status-go/services/accounts/accountsevent"
|
||||
"github.com/status-im/status-go/services/communitytokens"
|
||||
"github.com/status-im/status-go/services/communitytokens/communitytokensdatabase"
|
||||
"github.com/status-im/status-go/services/utils"
|
||||
"github.com/status-im/status-go/services/wallet/async"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
|
@ -102,7 +102,7 @@ type Manager struct {
|
|||
ContractMaker *contracts.ContractMaker
|
||||
networkManager *network.Manager
|
||||
stores []store // Set on init, not changed afterwards
|
||||
communityTokensDB *communitytokens.Database
|
||||
communityTokensDB *communitytokensdatabase.Database
|
||||
communityManager *community.Manager
|
||||
mediaServer *server.MediaServer
|
||||
walletFeed *event.Feed
|
||||
|
@ -178,7 +178,7 @@ func NewTokenManager(
|
|||
networkManager: networkManager,
|
||||
communityManager: communityManager,
|
||||
stores: stores,
|
||||
communityTokensDB: communitytokens.NewCommunityTokensDatabase(appDB),
|
||||
communityTokensDB: communitytokensdatabase.NewCommunityTokensDatabase(appDB),
|
||||
tokens: tokens,
|
||||
mediaServer: mediaServer,
|
||||
walletFeed: walletFeed,
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package signal
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/status-im/status-go/protocol/communities/token"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
// EventCommunityTokenTransactionStatusChanged is triggered when community token contract
|
||||
// transaction changed its status
|
||||
EventCommunityTokenTransactionStatusChanged = "communityToken.communityTokenTransactionStatusChanged"
|
||||
)
|
||||
|
||||
type CommunityTokenTransactionSignal struct {
|
||||
TransactionType string `json:"transactionType"`
|
||||
Success bool `json:"success"` // transaction's status
|
||||
Hash common.Hash `json:"hash"` // transaction hash
|
||||
CommunityToken *token.CommunityToken `json:"communityToken,omitempty"` // community token changed by transaction
|
||||
OwnerToken *token.CommunityToken `json:"ownerToken,omitempty"` // owner token emitted by deployment transaction
|
||||
MasterToken *token.CommunityToken `json:"masterToken,omitempty"` // master token emitted by deployment transaction
|
||||
ErrorString string `json:"errorString"` // information about failed operation
|
||||
}
|
||||
|
||||
func SendCommunityTokenTransactionStatusSignal(transactionType string, success bool, hash common.Hash,
|
||||
communityToken *token.CommunityToken, ownerToken *token.CommunityToken, masterToken *token.CommunityToken, errorString string) {
|
||||
send(EventCommunityTokenTransactionStatusChanged, CommunityTokenTransactionSignal{
|
||||
TransactionType: transactionType,
|
||||
Success: success,
|
||||
Hash: hash,
|
||||
CommunityToken: communityToken,
|
||||
OwnerToken: ownerToken,
|
||||
MasterToken: masterToken,
|
||||
ErrorString: errorString,
|
||||
})
|
||||
}
|
|
@ -343,14 +343,16 @@ func (tm *PendingTxTracker) emitNotifications(chainID common.ChainID, changes []
|
|||
}
|
||||
|
||||
// PendingTransaction called with autoDelete = false will keep the transaction in the database until it is confirmed by the caller using Delete
|
||||
func (tm *PendingTxTracker) TrackPendingTransaction(chainID common.ChainID, hash eth.Hash, from eth.Address, trType PendingTrxType, autoDelete AutoDeleteType) error {
|
||||
func (tm *PendingTxTracker) TrackPendingTransaction(chainID common.ChainID, hash eth.Hash, from eth.Address, to eth.Address, trType PendingTrxType, autoDelete AutoDeleteType, additionalData string) error {
|
||||
err := tm.addPending(&PendingTransaction{
|
||||
ChainID: chainID,
|
||||
Hash: hash,
|
||||
From: from,
|
||||
Timestamp: uint64(time.Now().Unix()),
|
||||
Type: trType,
|
||||
AutoDelete: &autoDelete,
|
||||
ChainID: chainID,
|
||||
Hash: hash,
|
||||
From: from,
|
||||
To: to,
|
||||
Timestamp: uint64(time.Now().Unix()),
|
||||
Type: trType,
|
||||
AutoDelete: &autoDelete,
|
||||
AdditionalData: additionalData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -290,7 +290,7 @@ func TestPendingTxTracker_MultipleClients(t *testing.T) {
|
|||
sub := eventFeed.Subscribe(eventChan)
|
||||
|
||||
for i := range txs {
|
||||
err := m.TrackPendingTransaction(txs[i].ChainID, txs[i].Hash, txs[i].From, txs[i].Type, AutoDelete)
|
||||
err := m.TrackPendingTransaction(txs[i].ChainID, txs[i].Hash, txs[i].From, txs[i].To, txs[i].Type, AutoDelete, "")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,7 @@ func TestPendingTxTracker_Watch(t *testing.T) {
|
|||
sub := eventFeed.Subscribe(eventChan)
|
||||
|
||||
// Track the first transaction
|
||||
err := m.TrackPendingTransaction(txs[1].ChainID, txs[1].Hash, txs[1].From, txs[1].Type, Keep)
|
||||
err := m.TrackPendingTransaction(txs[1].ChainID, txs[1].Hash, txs[1].From, txs[1].To, txs[1].Type, Keep, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Store the confirmed already
|
||||
|
@ -464,7 +464,7 @@ func TestPendingTxTracker_Watch_StatusChangeIncrementally(t *testing.T) {
|
|||
|
||||
for i := range txs {
|
||||
// Track the first transaction
|
||||
err := m.TrackPendingTransaction(txs[i].ChainID, txs[i].Hash, txs[i].From, txs[i].Type, Keep)
|
||||
err := m.TrackPendingTransaction(txs[i].ChainID, txs[i].Hash, txs[i].From, txs[i].To, txs[i].Type, Keep, "")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue