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.ChatService(accDB).Init(messenger)
|
||||||
b.statusNode.EnsService().Init(messenger.SyncEnsNamesWithDispatchMessage)
|
b.statusNode.EnsService().Init(messenger.SyncEnsNamesWithDispatchMessage)
|
||||||
|
b.statusNode.CommunityTokensService().Init(messenger)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -487,7 +487,7 @@ func (b *StatusNode) pendingTrackerService(walletFeed *event.Feed) *transactions
|
||||||
|
|
||||||
func (b *StatusNode) CommunityTokensService() *communitytokens.Service {
|
func (b *StatusNode) CommunityTokensService() *communitytokens.Service {
|
||||||
if b.communityTokensSrvc == nil {
|
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
|
return b.communityTokensSrvc
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,12 +42,12 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/requests"
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
"github.com/status-im/status-go/protocol/transport"
|
"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"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
walletcommon "github.com/status-im/status-go/services/wallet/common"
|
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/thirdparty"
|
||||||
"github.com/status-im/status-go/services/wallet/token"
|
"github.com/status-im/status-go/services/wallet/token"
|
||||||
"github.com/status-im/status-go/signal"
|
"github.com/status-im/status-go/signal"
|
||||||
|
"github.com/status-im/status-go/transactions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultAnnounceList = [][]string{
|
var defaultAnnounceList = [][]string{
|
||||||
|
@ -102,7 +102,7 @@ type Manager struct {
|
||||||
torrentConfig *params.TorrentConfig
|
torrentConfig *params.TorrentConfig
|
||||||
torrentClient *torrent.Client
|
torrentClient *torrent.Client
|
||||||
walletConfig *params.WalletConfig
|
walletConfig *params.WalletConfig
|
||||||
communityTokensService communitytokens.ServiceInterface
|
communityTokensService CommunityTokensServiceInterface
|
||||||
historyArchiveTasksWaitGroup sync.WaitGroup
|
historyArchiveTasksWaitGroup sync.WaitGroup
|
||||||
historyArchiveTasks sync.Map // stores `chan struct{}`
|
historyArchiveTasks sync.Map // stores `chan struct{}`
|
||||||
membersReevaluationTasks sync.Map // stores `membersReevaluationTask`
|
membersReevaluationTasks sync.Map // stores `membersReevaluationTask`
|
||||||
|
@ -190,7 +190,7 @@ type managerOptions struct {
|
||||||
tokenManager TokenManager
|
tokenManager TokenManager
|
||||||
collectiblesManager CollectiblesManager
|
collectiblesManager CollectiblesManager
|
||||||
walletConfig *params.WalletConfig
|
walletConfig *params.WalletConfig
|
||||||
communityTokensService communitytokens.ServiceInterface
|
communityTokensService CommunityTokensServiceInterface
|
||||||
permissionChecker PermissionChecker
|
permissionChecker PermissionChecker
|
||||||
|
|
||||||
// allowForcingCommunityMembersReevaluation indicates whether we should allow forcing community members reevaluation.
|
// allowForcingCommunityMembersReevaluation indicates whether we should allow forcing community members reevaluation.
|
||||||
|
@ -205,6 +205,26 @@ type TokenManager interface {
|
||||||
GetAllChainIDs() ([]uint64, error)
|
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 {
|
type DefaultTokenManager struct {
|
||||||
tokenManager *token.Manager
|
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) {
|
return func(opts *managerOptions) {
|
||||||
opts.communityTokensService = communityTokensService
|
opts.communityTokensService = communityTokensService
|
||||||
}
|
}
|
||||||
|
@ -4747,6 +4767,10 @@ func (m *Manager) GetCommunityToken(communityID string, chainID int, address str
|
||||||
return m.persistence.GetCommunityToken(communityID, chainID, address)
|
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) {
|
func (m *Manager) GetCommunityTokens(communityID string) ([]*community_token.CommunityToken, error) {
|
||||||
return m.persistence.GetCommunityTokens(communityID)
|
return m.persistence.GetCommunityTokens(communityID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1276,6 +1276,29 @@ func (p *Persistence) GetCommunityToken(communityID string, chainID int, address
|
||||||
return &token, nil
|
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) {
|
func (p *Persistence) getCommunityTokensInternal(rows *sql.Rows) ([]*token.CommunityToken, error) {
|
||||||
tokens := []*token.CommunityToken{}
|
tokens := []*token.CommunityToken{}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/requests"
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"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/services/wallet/bigint"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2061,7 +2060,7 @@ func testEventSenderAddTokenMasterAndOwnerToken(base CommunityEventsTestsInterfa
|
||||||
}
|
}
|
||||||
|
|
||||||
func addCommunityTokenToCommunityTokensService(base CommunityEventsTestsInterface, token *token.CommunityToken) {
|
func addCommunityTokenToCommunityTokensService(base CommunityEventsTestsInterface, token *token.CommunityToken) {
|
||||||
data := &communitytokens.CollectibleContractData{
|
data := &communities.CollectibleContractData{
|
||||||
TotalSupply: token.Supply,
|
TotalSupply: token.Supply,
|
||||||
Transferable: token.Transferable,
|
Transferable: token.Transferable,
|
||||||
RemoteBurnable: token.RemoteSelfDestruct,
|
RemoteBurnable: token.RemoteSelfDestruct,
|
||||||
|
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/communities/token"
|
"github.com/status-im/status-go/protocol/communities/token"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/requests"
|
"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"
|
walletToken "github.com/status-im/status-go/services/wallet/token"
|
||||||
"github.com/status-im/status-go/transactions"
|
"github.com/status-im/status-go/transactions"
|
||||||
)
|
)
|
||||||
|
@ -74,8 +73,8 @@ func (m *TokenManagerMock) FindOrCreateTokenByAddress(ctx context.Context, chain
|
||||||
}
|
}
|
||||||
|
|
||||||
type CollectiblesServiceMock struct {
|
type CollectiblesServiceMock struct {
|
||||||
Collectibles map[uint64]map[string]*communitytokens.CollectibleContractData
|
Collectibles map[uint64]map[string]*communities.CollectibleContractData
|
||||||
Assets map[uint64]map[string]*communitytokens.AssetContractData
|
Assets map[uint64]map[string]*communities.AssetContractData
|
||||||
Signers map[string]string
|
Signers map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +89,7 @@ func (c *CollectiblesServiceMock) SetSignerPubKey(ctx context.Context, chainID u
|
||||||
return "", nil
|
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]
|
collectibleContractData, dataExists := c.Collectibles[chainID][contractAddress]
|
||||||
if dataExists {
|
if dataExists {
|
||||||
return collectibleContractData, nil
|
return collectibleContractData, nil
|
||||||
|
@ -98,7 +97,7 @@ func (c *CollectiblesServiceMock) GetCollectibleContractData(chainID uint64, con
|
||||||
return nil, nil
|
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]
|
assetsContractData, dataExists := c.Assets[chainID][contractAddress]
|
||||||
if dataExists {
|
if dataExists {
|
||||||
return assetsContractData, nil
|
return assetsContractData, nil
|
||||||
|
@ -106,22 +105,22 @@ func (c *CollectiblesServiceMock) GetAssetContractData(chainID uint64, contractA
|
||||||
return nil, nil
|
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 {
|
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 {
|
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
|
c.Collectibles[chainID][contractAddress] = collectible
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CollectiblesServiceMock) SetMockCommunityTokenData(token *token.CommunityToken) {
|
func (c *CollectiblesServiceMock) SetMockCommunityTokenData(token *token.CommunityToken) {
|
||||||
if c.Collectibles == nil {
|
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,
|
TotalSupply: token.Supply,
|
||||||
Transferable: token.Transferable,
|
Transferable: token.Transferable,
|
||||||
RemoteBurnable: token.RemoteSelfDestruct,
|
RemoteBurnable: token.RemoteSelfDestruct,
|
||||||
|
@ -138,11 +137,11 @@ func (c *CollectiblesServiceMock) SafeGetSignerPubKey(ctx context.Context, chain
|
||||||
return c.Signers[communityID], nil
|
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 {
|
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
|
c.Assets[chainID][contractAddress] = assetData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +158,7 @@ type testCommunitiesMessengerConfig struct {
|
||||||
password string
|
password string
|
||||||
walletAddresses []string
|
walletAddresses []string
|
||||||
mockedBalances *map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
|
mockedBalances *map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
|
||||||
collectiblesService communitytokens.ServiceInterface
|
collectiblesService communities.CommunityTokensServiceInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcmc *testCommunitiesMessengerConfig) complete() error {
|
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/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/requests"
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"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/services/wallet/bigint"
|
||||||
"github.com/status-im/status-go/waku"
|
"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
|
// 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.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.john.identity.PublicKey))
|
||||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||||
|
|
||||||
// bob accepts community update
|
// bob accepts community update
|
||||||
_, err = WaitOnSignaledMessengerResponse(
|
_, err = WaitOnSignaledMessengerResponse(
|
||||||
|
@ -377,7 +376,7 @@ func (s *MessengerCommunitiesSignersSuite) TestAutoAcceptOnOwnershipChangeReques
|
||||||
// set john as contract owner
|
// set john as contract owner
|
||||||
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.john.identity.PublicKey))
|
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.john.identity.PublicKey))
|
||||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||||
|
|
||||||
hasTokenPermission := func(r *MessengerResponse) bool {
|
hasTokenPermission := func(r *MessengerResponse) bool {
|
||||||
return len(r.Communities()) > 0 && r.Communities()[0].HasTokenPermissions()
|
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
|
// 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.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.john.identity.PublicKey))
|
||||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||||
|
|
||||||
// alice accepts community update
|
// alice accepts community update
|
||||||
_, err = WaitOnSignaledMessengerResponse(
|
_, err = WaitOnSignaledMessengerResponse(
|
||||||
|
|
|
@ -62,7 +62,6 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/verification"
|
"github.com/status-im/status-go/protocol/verification"
|
||||||
"github.com/status-im/status-go/server"
|
"github.com/status-im/status-go/server"
|
||||||
"github.com/status-im/status-go/services/browsers"
|
"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"
|
ensservice "github.com/status-im/status-go/services/ens"
|
||||||
"github.com/status-im/status-go/services/ext/mailservers"
|
"github.com/status-im/status-go/services/ext/mailservers"
|
||||||
localnotifications "github.com/status-im/status-go/services/local-notifications"
|
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
|
// flag to enable backedup messages processing, false by default
|
||||||
processBackedupMessages bool
|
processBackedupMessages bool
|
||||||
|
|
||||||
communityTokensService communitytokens.ServiceInterface
|
communityTokensService communities.CommunityTokensServiceInterface
|
||||||
|
|
||||||
// used to track dispatched messages
|
// used to track dispatched messages
|
||||||
dispatchMessageTestCallback func(common.RawMessage)
|
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)
|
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) {
|
func (m *Messenger) GetCommunityTokens(communityID string) ([]*token.CommunityToken, error) {
|
||||||
return m.communitiesManager.GetCommunityTokens(communityID)
|
return m.communitiesManager.GetCommunityTokens(communityID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"github.com/status-im/status-go/rpc"
|
"github.com/status-im/status-go/rpc"
|
||||||
"github.com/status-im/status-go/server"
|
"github.com/status-im/status-go/server"
|
||||||
"github.com/status-im/status-go/services/browsers"
|
"github.com/status-im/status-go/services/browsers"
|
||||||
"github.com/status-im/status-go/services/communitytokens"
|
|
||||||
"github.com/status-im/status-go/wakuv2"
|
"github.com/status-im/status-go/wakuv2"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -90,7 +89,7 @@ type config struct {
|
||||||
torrentConfig *params.TorrentConfig
|
torrentConfig *params.TorrentConfig
|
||||||
walletConfig *params.WalletConfig
|
walletConfig *params.WalletConfig
|
||||||
walletService *wallet.Service
|
walletService *wallet.Service
|
||||||
communityTokensService communitytokens.ServiceInterface
|
communityTokensService communities.CommunityTokensServiceInterface
|
||||||
httpServer *server.MediaServer
|
httpServer *server.MediaServer
|
||||||
rpcClient *rpc.Client
|
rpcClient *rpc.Client
|
||||||
tokenManager communities.TokenManager
|
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 {
|
return func(c *config) error {
|
||||||
c.communityTokensService = s
|
c.communityTokensService = s
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -29,7 +29,6 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/requests"
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
"github.com/status-im/status-go/protocol/transport"
|
"github.com/status-im/status-go/protocol/transport"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"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"
|
mailserversDB "github.com/status-im/status-go/services/mailservers"
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
"github.com/status-im/status-go/t/helpers"
|
"github.com/status-im/status-go/t/helpers"
|
||||||
|
@ -1042,7 +1041,7 @@ func (s *MessengerStoreNodeRequestSuite) TestFetchRealCommunity() {
|
||||||
for _, communityToken := range communityTokens {
|
for _, communityToken := range communityTokens {
|
||||||
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(communityIDBytes, ownerPublicKey)
|
s.collectiblesServiceMock.SetSignerPubkeyForCommunity(communityIDBytes, ownerPublicKey)
|
||||||
s.collectiblesServiceMock.SetMockCollectibleContractData(communityToken.ChainID, communityToken.ContractAddress,
|
s.collectiblesServiceMock.SetMockCollectibleContractData(communityToken.ChainID, communityToken.ContractAddress,
|
||||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||||
}
|
}
|
||||||
|
|
||||||
results := map[string]singleResult{}
|
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
|
// 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.SetSignerPubkeyForCommunity(community.ID(), common.PubkeyToHex(&s.owner.identity.PublicKey))
|
||||||
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
s.collectiblesServiceMock.SetMockCollectibleContractData(chainID, tokenAddress,
|
||||||
&communitytokens.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
&communities.CollectibleContractData{TotalSupply: &bigint.BigInt{}})
|
||||||
|
|
||||||
community, err = s.owner.communitiesManager.GetByID(community.ID())
|
community, err = s.owner.communitiesManager.GetByID(community.ID())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
|
@ -2,11 +2,12 @@ package communitytokens
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
|
@ -19,6 +20,9 @@ import (
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/ownertoken"
|
"github.com/status-im/status-go/contracts/community-tokens/ownertoken"
|
||||||
communityownertokenregistry "github.com/status-im/status-go/contracts/community-tokens/registry"
|
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/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/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/services/utils"
|
"github.com/status-im/status-go/services/utils"
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
|
@ -39,6 +43,9 @@ type API struct {
|
||||||
type DeploymentDetails struct {
|
type DeploymentDetails struct {
|
||||||
ContractAddress string `json:"contractAddress"`
|
ContractAddress string `json:"contractAddress"`
|
||||||
TransactionHash string `json:"transactionHash"`
|
TransactionHash string `json:"transactionHash"`
|
||||||
|
CommunityToken *token.CommunityToken `json:"communityToken"`
|
||||||
|
OwnerToken *token.CommunityToken `json:"ownerToken"`
|
||||||
|
MasterToken *token.CommunityToken `json:"masterToken"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxSupply = 999999999
|
const maxSupply = 999999999
|
||||||
|
@ -53,6 +60,11 @@ type DeploymentParameters struct {
|
||||||
TokenURI string `json:"tokenUri"`
|
TokenURI string `json:"tokenUri"`
|
||||||
OwnerTokenAddress string `json:"ownerTokenAddress"`
|
OwnerTokenAddress string `json:"ownerTokenAddress"`
|
||||||
MasterTokenAddress string `json:"masterTokenAddress"`
|
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 {
|
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) {
|
func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deploymentParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||||
|
|
||||||
err := deploymentParameters.Validate(false)
|
err := deploymentParameters.Validate(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DeploymentDetails{}, err
|
return DeploymentDetails{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
||||||
|
|
||||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
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())
|
log.Error(err.Error())
|
||||||
return DeploymentDetails{}, err
|
return DeploymentDetails{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
address, tx, _, err := collectibles.DeployCollectibles(transactOpts, ethClient, deploymentParameters.Name,
|
address, tx, _, err := collectibles.DeployCollectibles(transactOpts, ethClient, deploymentParameters.Name,
|
||||||
deploymentParameters.Symbol, deploymentParameters.GetSupply(),
|
deploymentParameters.Symbol, deploymentParameters.GetSupply(),
|
||||||
deploymentParameters.RemoteSelfDestruct, deploymentParameters.Transferable,
|
deploymentParameters.RemoteSelfDestruct, deploymentParameters.Transferable,
|
||||||
|
@ -120,15 +129,26 @@ func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deployme
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
address,
|
||||||
transactions.DeployCommunityToken,
|
transactions.DeployCommunityToken,
|
||||||
transactions.AutoDelete,
|
transactions.Keep,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
log.Error("TrackPendingTransaction error", "error", err)
|
||||||
return DeploymentDetails{}, 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) {
|
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,
|
func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
|
||||||
ownerTokenParameters DeploymentParameters, masterTokenParameters DeploymentParameters,
|
ownerTokenParameters DeploymentParameters, masterTokenParameters DeploymentParameters,
|
||||||
signature string, communityID string, signerPubKey string,
|
signerPubKey string, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||||
txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
|
||||||
err := ownerTokenParameters.Validate(false)
|
err := ownerTokenParameters.Validate(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DeploymentDetails{}, err
|
return DeploymentDetails{}, err
|
||||||
|
@ -197,7 +216,12 @@ func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
|
||||||
BaseURI: masterTokenParameters.TokenURI,
|
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 {
|
if err != nil {
|
||||||
return DeploymentDetails{}, err
|
return DeploymentDetails{}, err
|
||||||
}
|
}
|
||||||
|
@ -211,81 +235,38 @@ func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
|
||||||
return DeploymentDetails{}, err
|
return DeploymentDetails{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("Contract deployed hash:", tx.Hash().String())
|
||||||
|
|
||||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
err = api.s.pendingTracker.TrackPendingTransaction(
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
common.Address{},
|
||||||
transactions.DeployOwnerToken,
|
transactions.DeployOwnerToken,
|
||||||
transactions.AutoDelete,
|
transactions.Keep,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
log.Error("TrackPendingTransaction error", "error", err)
|
||||||
return DeploymentDetails{}, err
|
return DeploymentDetails{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return DeploymentDetails{"", tx.Hash().Hex()}, nil
|
savedOwnerToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), ownerTokenParameters, txArgs.From.Hex(),
|
||||||
}
|
api.s.TemporaryOwnerContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.OwnerLevel)
|
||||||
|
|
||||||
func (api *API) GetMasterTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
|
|
||||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return DeploymentDetails{}, err
|
||||||
}
|
}
|
||||||
|
savedMasterToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), masterTokenParameters, txArgs.From.Hex(),
|
||||||
receipt, err := ethClient.TransactionReceipt(ctx, common.HexToHash(txHash))
|
api.s.TemporaryMasterContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.MasterLevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return DeploymentDetails{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
deployerContractInst, err := api.NewCommunityTokenDeployerInstance(chainID)
|
return DeploymentDetails{
|
||||||
if err != nil {
|
ContractAddress: "",
|
||||||
return "", err
|
TransactionHash: tx.Hash().Hex(),
|
||||||
}
|
OwnerToken: savedOwnerToken,
|
||||||
|
MasterToken: savedMasterToken}, nil
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
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),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
address,
|
||||||
transactions.DeployCommunityToken,
|
transactions.DeployCommunityToken,
|
||||||
transactions.AutoDelete,
|
transactions.Keep,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
log.Error("TrackPendingTransaction error", "error", err)
|
||||||
return DeploymentDetails{}, 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%
|
// 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,
|
func (api *API) DeployOwnerTokenEstimate(ctx context.Context, chainID uint64, fromAddress string,
|
||||||
ownerTokenParameters DeploymentParameters, masterTokenParameters DeploymentParameters,
|
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)
|
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
|
@ -432,7 +424,12 @@ func (api *API) DeployOwnerTokenEstimate(ctx context.Context, chainID uint64, fr
|
||||||
BaseURI: masterTokenParameters.TokenURI,
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -531,8 +528,10 @@ func (api *API) MintTokens(ctx context.Context, chainID uint64, contractAddress
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
common.HexToAddress(contractAddress),
|
||||||
transactions.AirdropCommunityToken,
|
transactions.AirdropCommunityToken,
|
||||||
transactions.AutoDelete,
|
transactions.Keep,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
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
|
// 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)
|
err := api.validateTokens(tokenIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -641,8 +640,10 @@ func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
common.HexToAddress(contractAddress),
|
||||||
transactions.RemoteDestructCollectible,
|
transactions.RemoteDestructCollectible,
|
||||||
transactions.AutoDelete,
|
transactions.Keep,
|
||||||
|
additionalData,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
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
|
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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -801,8 +768,10 @@ func (api *API) Burn(ctx context.Context, chainID uint64, contractAddress string
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
common.HexToAddress(contractAddress),
|
||||||
transactions.BurnCommunityToken,
|
transactions.BurnCommunityToken,
|
||||||
transactions.AutoDelete,
|
transactions.Keep,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
log.Error("TrackPendingTransaction error", "error", err)
|
||||||
|
|
|
@ -19,37 +19,37 @@ func TestDeploymentParameters(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "emptyName",
|
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,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "emptySymbol",
|
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,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negativeSupply",
|
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,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zeroSupply",
|
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,
|
isError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negativeSupplyAndInfinite",
|
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,
|
isError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "supplyGreaterThanMax",
|
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,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "supplyIsMax",
|
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,
|
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)
|
requiredSupply := big.NewInt(123)
|
||||||
require.Equal(t, notInfiniteSupplyParams.GetSupply(), requiredSupply)
|
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()
|
requiredSupply = infiniteSupplyParams.GetInfiniteSupply()
|
||||||
require.Equal(t, infiniteSupplyParams.GetSupply(), requiredSupply)
|
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 (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
|
@ -1,4 +1,4 @@
|
||||||
package communitytokens
|
package communitytokensdatabase
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
|
@ -13,6 +13,7 @@ import (
|
||||||
communitytokendeployer "github.com/status-im/status-go/contracts/community-tokens/deployer"
|
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/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"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/rpc"
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
)
|
)
|
||||||
|
@ -71,7 +72,7 @@ func (m *Manager) GetAssetContractInstance(chainID uint64, contractAddress strin
|
||||||
return contractInst, nil
|
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}
|
callOpts := &bind.CallOpts{Context: context.Background(), Pending: false}
|
||||||
|
|
||||||
contract, err := m.GetCollectiblesContractInstance(chainID, contractAddress)
|
contract, err := m.GetCollectiblesContractInstance(chainID, contractAddress)
|
||||||
|
@ -91,7 +92,7 @@ func (m *Manager) GetCollectibleContractData(chainID uint64, contractAddress str
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CollectibleContractData{
|
return &communities.CollectibleContractData{
|
||||||
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
||||||
Transferable: transferable,
|
Transferable: transferable,
|
||||||
RemoteBurnable: remoteBurnable,
|
RemoteBurnable: remoteBurnable,
|
||||||
|
@ -99,7 +100,7 @@ func (m *Manager) GetCollectibleContractData(chainID uint64, contractAddress str
|
||||||
}, nil
|
}, 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}
|
callOpts := &bind.CallOpts{Context: context.Background(), Pending: false}
|
||||||
contract, err := m.GetAssetContractInstance(chainID, contractAddress)
|
contract, err := m.GetAssetContractInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -110,7 +111,7 @@ func (m *Manager) GetAssetContractData(chainID uint64, contractAddress string) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &AssetContractData{
|
return &communities.AssetContractData{
|
||||||
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
||||||
InfiniteSupply: GetInfiniteSupply().Cmp(totalSupply) == 0,
|
InfiniteSupply: GetInfiniteSupply().Cmp(totalSupply) == 0,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -3,49 +3,60 @@ package communitytokens
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
ethRpc "github.com/ethereum/go-ethereum/rpc"
|
ethRpc "github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/status-im/status-go/account"
|
"github.com/status-im/status-go/account"
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/ownertoken"
|
"github.com/status-im/status-go/contracts/community-tokens/ownertoken"
|
||||||
communityownertokenregistry "github.com/status-im/status-go/contracts/community-tokens/registry"
|
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/eth-node/types"
|
||||||
"github.com/status-im/status-go/params"
|
"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/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/utils"
|
||||||
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
wcommon "github.com/status-im/status-go/services/wallet/common"
|
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"
|
"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
|
// Collectibles service
|
||||||
type Service struct {
|
type Service struct {
|
||||||
manager *Manager
|
manager *Manager
|
||||||
accountsManager *account.GethManager
|
accountsManager *account.GethManager
|
||||||
pendingTracker *transactions.PendingTxTracker
|
pendingTracker *transactions.PendingTxTracker
|
||||||
config *params.NodeConfig
|
config *params.NodeConfig
|
||||||
db *Database
|
db *communitytokensdatabase.Database
|
||||||
|
Messenger *protocol.Messenger
|
||||||
|
walletFeed *event.Feed
|
||||||
|
walletWatcher *walletevent.Watcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a new Collectibles Service.
|
// 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{
|
return &Service{
|
||||||
manager: &Manager{rpcClient: rpcClient},
|
manager: &Manager{rpcClient: rpcClient},
|
||||||
accountsManager: accountsManager,
|
accountsManager: accountsManager,
|
||||||
pendingTracker: pendingTracker,
|
pendingTracker: pendingTracker,
|
||||||
config: config,
|
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.
|
// Start is run when a service is started.
|
||||||
func (s *Service) Start() error {
|
func (s *Service) Start() error {
|
||||||
|
|
||||||
|
s.walletWatcher = walletevent.NewWatcher(s.walletFeed, s.handleWalletEvent)
|
||||||
|
s.walletWatcher.Start()
|
||||||
|
|
||||||
return nil
|
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.
|
// Stop is run when a service is stopped.
|
||||||
func (s *Service) Stop() error {
|
func (s *Service) Stop() error {
|
||||||
|
s.walletWatcher.Stop()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) Init(messenger *protocol.Messenger) {
|
||||||
|
s.Messenger = messenger
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) NewCommunityOwnerTokenRegistryInstance(chainID uint64, contractAddress string) (*communityownertokenregistry.CommunityOwnerTokenRegistry, error) {
|
func (s *Service) NewCommunityOwnerTokenRegistryInstance(chainID uint64, contractAddress string) (*communityownertokenregistry.CommunityOwnerTokenRegistry, error) {
|
||||||
backend, err := s.manager.rpcClient.EthClient(chainID)
|
backend, err := s.manager.rpcClient.EthClient(chainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,11 +320,11 @@ func (s *Service) SafeGetOwnerTokenAddress(ctx context.Context, chainID uint64,
|
||||||
return ownerTokenAddress.Hex(), err
|
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)
|
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)
|
return s.manager.GetAssetContractData(chainID, contractAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +354,10 @@ func (s *Service) SetSignerPubKey(ctx context.Context, chainID uint64, contractA
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
common.HexToAddress(contractAddress),
|
||||||
transactions.SetSignerPublicKey,
|
transactions.SetSignerPublicKey,
|
||||||
transactions.AutoDelete,
|
transactions.AutoDelete,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
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
|
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),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
registryAddr,
|
||||||
transactions.ReleaseENS,
|
transactions.ReleaseENS,
|
||||||
transactions.AutoDelete,
|
transactions.AutoDelete,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
log.Error("TrackPendingTransaction error", "error", err)
|
||||||
|
@ -484,8 +486,10 @@ func (api *API) Register(ctx context.Context, chainID uint64, txArgs transaction
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
registryAddr,
|
||||||
transactions.RegisterENS,
|
transactions.RegisterENS,
|
||||||
transactions.AutoDelete,
|
transactions.AutoDelete,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
log.Error("TrackPendingTransaction error", "error", err)
|
||||||
|
@ -600,8 +604,10 @@ func (api *API) SetPubKey(ctx context.Context, chainID uint64, txArgs transactio
|
||||||
wcommon.ChainID(chainID),
|
wcommon.ChainID(chainID),
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
common.Address(txArgs.From),
|
common.Address(txArgs.From),
|
||||||
|
*resolverAddress,
|
||||||
transactions.SetPubKey,
|
transactions.SetPubKey,
|
||||||
transactions.AutoDelete,
|
transactions.AutoDelete,
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TrackPendingTransaction error", "error", err)
|
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/rpc/network"
|
||||||
"github.com/status-im/status-go/server"
|
"github.com/status-im/status-go/server"
|
||||||
"github.com/status-im/status-go/services/accounts/accountsevent"
|
"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/utils"
|
||||||
"github.com/status-im/status-go/services/wallet/async"
|
"github.com/status-im/status-go/services/wallet/async"
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
|
@ -102,7 +102,7 @@ type Manager struct {
|
||||||
ContractMaker *contracts.ContractMaker
|
ContractMaker *contracts.ContractMaker
|
||||||
networkManager *network.Manager
|
networkManager *network.Manager
|
||||||
stores []store // Set on init, not changed afterwards
|
stores []store // Set on init, not changed afterwards
|
||||||
communityTokensDB *communitytokens.Database
|
communityTokensDB *communitytokensdatabase.Database
|
||||||
communityManager *community.Manager
|
communityManager *community.Manager
|
||||||
mediaServer *server.MediaServer
|
mediaServer *server.MediaServer
|
||||||
walletFeed *event.Feed
|
walletFeed *event.Feed
|
||||||
|
@ -178,7 +178,7 @@ func NewTokenManager(
|
||||||
networkManager: networkManager,
|
networkManager: networkManager,
|
||||||
communityManager: communityManager,
|
communityManager: communityManager,
|
||||||
stores: stores,
|
stores: stores,
|
||||||
communityTokensDB: communitytokens.NewCommunityTokensDatabase(appDB),
|
communityTokensDB: communitytokensdatabase.NewCommunityTokensDatabase(appDB),
|
||||||
tokens: tokens,
|
tokens: tokens,
|
||||||
mediaServer: mediaServer,
|
mediaServer: mediaServer,
|
||||||
walletFeed: walletFeed,
|
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
|
// 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{
|
err := tm.addPending(&PendingTransaction{
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
From: from,
|
From: from,
|
||||||
|
To: to,
|
||||||
Timestamp: uint64(time.Now().Unix()),
|
Timestamp: uint64(time.Now().Unix()),
|
||||||
Type: trType,
|
Type: trType,
|
||||||
AutoDelete: &autoDelete,
|
AutoDelete: &autoDelete,
|
||||||
|
AdditionalData: additionalData,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -290,7 +290,7 @@ func TestPendingTxTracker_MultipleClients(t *testing.T) {
|
||||||
sub := eventFeed.Subscribe(eventChan)
|
sub := eventFeed.Subscribe(eventChan)
|
||||||
|
|
||||||
for i := range txs {
|
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)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ func TestPendingTxTracker_Watch(t *testing.T) {
|
||||||
sub := eventFeed.Subscribe(eventChan)
|
sub := eventFeed.Subscribe(eventChan)
|
||||||
|
|
||||||
// Track the first transaction
|
// 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)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Store the confirmed already
|
// Store the confirmed already
|
||||||
|
@ -464,7 +464,7 @@ func TestPendingTxTracker_Watch_StatusChangeIncrementally(t *testing.T) {
|
||||||
|
|
||||||
for i := range txs {
|
for i := range txs {
|
||||||
// Track the first transaction
|
// 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)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue