mirror of
https://github.com/status-im/status-go.git
synced 2025-01-29 16:06:47 +00:00
chore(communities)!: remove communitytokens package
This is a breaking change which removes `communitytokens` package. This commit removes old `communitytokens` package, cause previously added `communitytokensv2` package, which is in use now, will be renamed to `communitytokens` in next commit.
This commit is contained in:
parent
6dcc4bd35d
commit
988894ccaf
@ -2692,7 +2692,7 @@ func (b *GethStatusBackend) injectAccountsIntoWakuService(w wakutypes.WakuKeyMan
|
|||||||
}
|
}
|
||||||
|
|
||||||
if st != nil {
|
if st != nil {
|
||||||
if err := st.InitProtocol(b.statusNode.GethNode().Config().Name, identity, b.appDB, b.walletDB, b.statusNode.HTTPServer(), b.multiaccountsDB, acc, b.accountManager, b.statusNode.RPCClient(), b.statusNode.WalletService(), b.statusNode.CommunityTokensService(), b.statusNode.WakuV2Service(), logutils.ZapLogger(), b.statusNode.AccountsFeed()); err != nil {
|
if err := st.InitProtocol(b.statusNode.GethNode().Config().Name, identity, b.appDB, b.walletDB, b.statusNode.HTTPServer(), b.multiaccountsDB, acc, b.accountManager, b.statusNode.RPCClient(), b.statusNode.WalletService(), b.statusNode.CommunityTokensServiceV2(), b.statusNode.WakuV2Service(), logutils.ZapLogger(), b.statusNode.AccountsFeed()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Set initial connection state
|
// Set initial connection state
|
||||||
@ -2709,7 +2709,6 @@ func (b *GethStatusBackend) injectAccountsIntoWakuService(w wakutypes.WakuKeyMan
|
|||||||
}
|
}
|
||||||
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)
|
|
||||||
b.statusNode.CommunityTokensServiceV2().Init(messenger)
|
b.statusNode.CommunityTokensServiceV2().Init(messenger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ import (
|
|||||||
appmetricsservice "github.com/status-im/status-go/services/appmetrics"
|
appmetricsservice "github.com/status-im/status-go/services/appmetrics"
|
||||||
"github.com/status-im/status-go/services/browsers"
|
"github.com/status-im/status-go/services/browsers"
|
||||||
"github.com/status-im/status-go/services/chat"
|
"github.com/status-im/status-go/services/chat"
|
||||||
"github.com/status-im/status-go/services/communitytokens"
|
|
||||||
"github.com/status-im/status-go/services/communitytokensv2"
|
"github.com/status-im/status-go/services/communitytokensv2"
|
||||||
"github.com/status-im/status-go/services/connector"
|
"github.com/status-im/status-go/services/connector"
|
||||||
"github.com/status-im/status-go/services/ens"
|
"github.com/status-im/status-go/services/ens"
|
||||||
@ -129,7 +128,6 @@ type StatusNode struct {
|
|||||||
wakuV2Srvc *wakuv2.Waku
|
wakuV2Srvc *wakuv2.Waku
|
||||||
wakuV2ExtSrvc *wakuv2ext.Service
|
wakuV2ExtSrvc *wakuv2ext.Service
|
||||||
ensSrvc *ens.Service
|
ensSrvc *ens.Service
|
||||||
communityTokensSrvc *communitytokens.Service
|
|
||||||
communityTokensSrvcV2 *communitytokensv2.Service
|
communityTokensSrvcV2 *communitytokensv2.Service
|
||||||
gifSrvc *gif.Service
|
gifSrvc *gif.Service
|
||||||
stickersSrvc *stickers.Service
|
stickersSrvc *stickers.Service
|
||||||
@ -520,7 +518,7 @@ func (n *StatusNode) stop() error {
|
|||||||
n.wakuV2Srvc = nil
|
n.wakuV2Srvc = nil
|
||||||
n.wakuV2ExtSrvc = nil
|
n.wakuV2ExtSrvc = nil
|
||||||
n.ensSrvc = nil
|
n.ensSrvc = nil
|
||||||
n.communityTokensSrvc = nil
|
n.communityTokensSrvcV2 = nil
|
||||||
n.stickersSrvc = nil
|
n.stickersSrvc = nil
|
||||||
n.connectorSrvc = nil
|
n.connectorSrvc = nil
|
||||||
n.publicMethods = make(map[string]bool)
|
n.publicMethods = make(map[string]bool)
|
||||||
|
@ -40,7 +40,6 @@ import (
|
|||||||
appmetricsservice "github.com/status-im/status-go/services/appmetrics"
|
appmetricsservice "github.com/status-im/status-go/services/appmetrics"
|
||||||
"github.com/status-im/status-go/services/browsers"
|
"github.com/status-im/status-go/services/browsers"
|
||||||
"github.com/status-im/status-go/services/chat"
|
"github.com/status-im/status-go/services/chat"
|
||||||
"github.com/status-im/status-go/services/communitytokens"
|
|
||||||
"github.com/status-im/status-go/services/communitytokensv2"
|
"github.com/status-im/status-go/services/communitytokensv2"
|
||||||
"github.com/status-im/status-go/services/connector"
|
"github.com/status-im/status-go/services/connector"
|
||||||
"github.com/status-im/status-go/services/ens"
|
"github.com/status-im/status-go/services/ens"
|
||||||
@ -97,7 +96,6 @@ func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server
|
|||||||
services = append(services, b.statusPublicService())
|
services = append(services, b.statusPublicService())
|
||||||
services = append(services, b.pendingTrackerService(&b.walletFeed))
|
services = append(services, b.pendingTrackerService(&b.walletFeed))
|
||||||
services = append(services, b.ensService(b.timeSourceNow()))
|
services = append(services, b.ensService(b.timeSourceNow()))
|
||||||
services = append(services, b.CommunityTokensService())
|
|
||||||
services = append(services, b.CommunityTokensServiceV2())
|
services = append(services, b.CommunityTokensServiceV2())
|
||||||
services = append(services, b.stickersService(accDB))
|
services = append(services, b.stickersService(accDB))
|
||||||
services = append(services, b.updatesService())
|
services = append(services, b.updatesService())
|
||||||
@ -504,13 +502,6 @@ func (b *StatusNode) pendingTrackerService(walletFeed *event.Feed) *transactions
|
|||||||
return b.pendingTracker
|
return b.pendingTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
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.walletFeed, b.transactor)
|
|
||||||
}
|
|
||||||
return b.communityTokensSrvc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *StatusNode) CommunityTokensServiceV2() *communitytokensv2.Service {
|
func (b *StatusNode) CommunityTokensServiceV2() *communitytokensv2.Service {
|
||||||
if b.communityTokensSrvcV2 == nil {
|
if b.communityTokensSrvcV2 == nil {
|
||||||
b.communityTokensSrvcV2 = communitytokensv2.NewService(b.rpcClient, b.gethAccountManager, b.config, b.appDB, &b.walletFeed, b.transactor)
|
b.communityTokensSrvcV2 = communitytokensv2.NewService(b.rpcClient, b.gethAccountManager, b.config, b.appDB, &b.walletFeed, b.transactor)
|
||||||
|
@ -44,7 +44,6 @@ import (
|
|||||||
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/services/wallet/wallettypes"
|
|
||||||
"github.com/status-im/status-go/signal"
|
"github.com/status-im/status-go/signal"
|
||||||
|
|
||||||
wakutypes "github.com/status-im/status-go/waku/types"
|
wakutypes "github.com/status-im/status-go/waku/types"
|
||||||
@ -270,7 +269,6 @@ type AssetContractData struct {
|
|||||||
|
|
||||||
type CommunityTokensServiceInterface interface {
|
type CommunityTokensServiceInterface interface {
|
||||||
GetCollectibleContractData(chainID uint64, contractAddress string) (*CollectibleContractData, error)
|
GetCollectibleContractData(chainID uint64, contractAddress string) (*CollectibleContractData, error)
|
||||||
SetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string, txArgs wallettypes.SendTxArgs, password string, newSignerPubKey string) (string, error)
|
|
||||||
GetAssetContractData(chainID uint64, contractAddress string) (*AssetContractData, error)
|
GetAssetContractData(chainID uint64, contractAddress string) (*AssetContractData, error)
|
||||||
SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error)
|
SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error)
|
||||||
DeploymentSignatureDigest(chainID uint64, addressFrom string, communityID string) ([]byte, error)
|
DeploymentSignatureDigest(chainID uint64, addressFrom string, communityID string) ([]byte, error)
|
||||||
|
@ -30,7 +30,6 @@ import (
|
|||||||
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"
|
||||||
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/services/wallet/wallettypes"
|
|
||||||
|
|
||||||
wakutypes "github.com/status-im/status-go/waku/types"
|
wakutypes "github.com/status-im/status-go/waku/types"
|
||||||
)
|
)
|
||||||
@ -203,10 +202,6 @@ func (c *CollectiblesServiceMock) SetSignerPubkeyForCommunity(communityID []byte
|
|||||||
c.Signers[types.EncodeHex(communityID)] = signerPubKey
|
c.Signers[types.EncodeHex(communityID)] = signerPubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CollectiblesServiceMock) SetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string, txArgs wallettypes.SendTxArgs, password string, newSignerPubKey string) (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CollectiblesServiceMock) GetCollectibleContractData(chainID uint64, contractAddress string) (*communities.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 {
|
||||||
|
@ -1,502 +0,0 @@
|
|||||||
package communitytokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/assets"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/collectibles"
|
|
||||||
communitytokendeployer "github.com/status-im/status-go/contracts/community-tokens/deployer"
|
|
||||||
"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/logutils"
|
|
||||||
"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"
|
|
||||||
wcommon "github.com/status-im/status-go/services/wallet/common"
|
|
||||||
"github.com/status-im/status-go/services/wallet/requests"
|
|
||||||
"github.com/status-im/status-go/services/wallet/responses"
|
|
||||||
"github.com/status-im/status-go/services/wallet/wallettypes"
|
|
||||||
"github.com/status-im/status-go/transactions"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewAPI(s *Service) *API {
|
|
||||||
return &API{
|
|
||||||
s: s,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type API struct {
|
|
||||||
s *Service
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deploymentParameters requests.DeploymentParameters, txArgs wallettypes.SendTxArgs, password string) (responses.DeploymentDetails, error) {
|
|
||||||
err := deploymentParameters.Validate(false)
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.VerifyPasswordAndGetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
address, tx, _, err := collectibles.DeployCollectibles(transactOpts, ethClient, deploymentParameters.Name,
|
|
||||||
deploymentParameters.Symbol, deploymentParameters.GetSupply(),
|
|
||||||
deploymentParameters.RemoteSelfDestruct, deploymentParameters.Transferable,
|
|
||||||
deploymentParameters.TokenURI, deploymentParameters.OwnerTokenAddress,
|
|
||||||
deploymentParameters.MasterTokenAddress)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
tx.Hash(),
|
|
||||||
common.Address(txArgs.From),
|
|
||||||
address,
|
|
||||||
transactions.DeployCommunityToken,
|
|
||||||
transactions.Keep,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error("TrackPendingTransaction error", zap.Error(err))
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
savedCommunityToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), deploymentParameters, txArgs.From.Hex(), address.Hex(),
|
|
||||||
protobuf.CommunityTokenType_ERC721, token.CommunityLevel, tx.Hash().Hex())
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return responses.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) {
|
|
||||||
if len(sig) != crypto.SignatureLength {
|
|
||||||
return [32]byte{}, [32]byte{}, 0, fmt.Errorf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength)
|
|
||||||
}
|
|
||||||
copy(r[:], sig[:32])
|
|
||||||
copy(s[:], sig[32:64])
|
|
||||||
v = sig[64] + 27
|
|
||||||
return r, s, v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func prepareDeploymentSignatureStruct(signature string, communityID string, addressFrom common.Address) (communitytokendeployer.CommunityTokenDeployerDeploymentSignature, error) {
|
|
||||||
r, s, v, err := decodeSignature(common.FromHex(signature))
|
|
||||||
if err != nil {
|
|
||||||
return communitytokendeployer.CommunityTokenDeployerDeploymentSignature{}, err
|
|
||||||
}
|
|
||||||
communityEthAddress, err := convert33BytesPubKeyToEthAddress(communityID)
|
|
||||||
if err != nil {
|
|
||||||
return communitytokendeployer.CommunityTokenDeployerDeploymentSignature{}, err
|
|
||||||
}
|
|
||||||
communitySignature := communitytokendeployer.CommunityTokenDeployerDeploymentSignature{
|
|
||||||
V: v,
|
|
||||||
R: r,
|
|
||||||
S: s,
|
|
||||||
Deployer: addressFrom,
|
|
||||||
Signer: communityEthAddress,
|
|
||||||
}
|
|
||||||
return communitySignature, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64,
|
|
||||||
ownerTokenParameters requests.DeploymentParameters, masterTokenParameters requests.DeploymentParameters,
|
|
||||||
signerPubKey string, txArgs wallettypes.SendTxArgs, password string) (responses.DeploymentDetails, error) {
|
|
||||||
err := ownerTokenParameters.Validate(false)
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(signerPubKey) <= 0 {
|
|
||||||
return responses.DeploymentDetails{}, fmt.Errorf("signerPubKey is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = masterTokenParameters.Validate(false)
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.VerifyPasswordAndGetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
deployerContractInst, err := api.NewCommunityTokenDeployerInstance(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ownerTokenConfig := communitytokendeployer.CommunityTokenDeployerTokenConfig{
|
|
||||||
Name: ownerTokenParameters.Name,
|
|
||||||
Symbol: ownerTokenParameters.Symbol,
|
|
||||||
BaseURI: ownerTokenParameters.TokenURI,
|
|
||||||
}
|
|
||||||
|
|
||||||
masterTokenConfig := communitytokendeployer.CommunityTokenDeployerTokenConfig{
|
|
||||||
Name: masterTokenParameters.Name,
|
|
||||||
Symbol: masterTokenParameters.Symbol,
|
|
||||||
BaseURI: masterTokenParameters.TokenURI,
|
|
||||||
}
|
|
||||||
|
|
||||||
signature, err := api.s.Messenger.CreateCommunityTokenDeploymentSignature(context.Background(), chainID, txArgs.From.Hex(), ownerTokenParameters.CommunityID)
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
communitySignature, err := prepareDeploymentSignatureStruct(types.HexBytes(signature).String(), ownerTokenParameters.CommunityID, common.Address(txArgs.From))
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
logutils.ZapLogger().Debug("Prepare deployment", zap.Any("signature", communitySignature))
|
|
||||||
|
|
||||||
tx, err := deployerContractInst.Deploy(transactOpts, ownerTokenConfig, masterTokenConfig, communitySignature, common.FromHex(signerPubKey))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
logutils.ZapLogger().Debug("Contract deployed", zap.Stringer("hash", tx.Hash()))
|
|
||||||
|
|
||||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
tx.Hash(),
|
|
||||||
common.Address(txArgs.From),
|
|
||||||
common.Address{},
|
|
||||||
transactions.DeployOwnerToken,
|
|
||||||
transactions.Keep,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error("TrackPendingTransaction error", zap.Error(err))
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
savedOwnerToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), ownerTokenParameters, txArgs.From.Hex(),
|
|
||||||
api.s.TemporaryOwnerContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.OwnerLevel, tx.Hash().Hex())
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
savedMasterToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), masterTokenParameters, txArgs.From.Hex(),
|
|
||||||
api.s.TemporaryMasterContractAddress(tx.Hash().Hex()), protobuf.CommunityTokenType_ERC721, token.MasterLevel, tx.Hash().Hex())
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return responses.DeploymentDetails{
|
|
||||||
ContractAddress: "",
|
|
||||||
TransactionHash: tx.Hash().Hex(),
|
|
||||||
OwnerToken: savedOwnerToken,
|
|
||||||
MasterToken: savedMasterToken}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// recovery function which starts transaction tracking again
|
|
||||||
func (api *API) ReTrackOwnerTokenDeploymentTransaction(ctx context.Context, chainID uint64, contractAddress string) error {
|
|
||||||
return api.s.ReTrackOwnerTokenDeploymentTransaction(ctx, chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentParameters requests.DeploymentParameters, txArgs wallettypes.SendTxArgs, password string) (responses.DeploymentDetails, error) {
|
|
||||||
|
|
||||||
err := deploymentParameters.Validate(true)
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.VerifyPasswordAndGetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
ethClient, err := api.s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
const decimals = 18
|
|
||||||
address, tx, _, err := assets.DeployAssets(transactOpts, ethClient, deploymentParameters.Name,
|
|
||||||
deploymentParameters.Symbol, decimals, deploymentParameters.GetSupply(),
|
|
||||||
deploymentParameters.TokenURI,
|
|
||||||
deploymentParameters.OwnerTokenAddress,
|
|
||||||
deploymentParameters.MasterTokenAddress)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
tx.Hash(),
|
|
||||||
common.Address(txArgs.From),
|
|
||||||
address,
|
|
||||||
transactions.DeployCommunityToken,
|
|
||||||
transactions.Keep,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error("TrackPendingTransaction error", zap.Error(err))
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
savedCommunityToken, err := api.s.CreateCommunityTokenAndSave(int(chainID), deploymentParameters, txArgs.From.Hex(), address.Hex(),
|
|
||||||
protobuf.CommunityTokenType_ERC20, token.CommunityLevel, tx.Hash().Hex())
|
|
||||||
if err != nil {
|
|
||||||
return responses.DeploymentDetails{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return responses.DeploymentDetails{
|
|
||||||
ContractAddress: address.Hex(),
|
|
||||||
TransactionHash: tx.Hash().Hex(),
|
|
||||||
CommunityToken: savedCommunityToken}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) DeployCollectiblesEstimate(ctx context.Context, chainID uint64, fromAddress string) (*CommunityTokenFees, error) {
|
|
||||||
return api.s.deployCollectiblesEstimate(ctx, chainID, fromAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) DeployAssetsEstimate(ctx context.Context, chainID uint64, fromAddress string) (*CommunityTokenFees, error) {
|
|
||||||
return api.s.deployAssetsEstimate(ctx, chainID, fromAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) DeployOwnerTokenEstimate(ctx context.Context, chainID uint64, fromAddress string,
|
|
||||||
ownerTokenParameters requests.DeploymentParameters, masterTokenParameters requests.DeploymentParameters,
|
|
||||||
communityID string, signerPubKey string) (*CommunityTokenFees, error) {
|
|
||||||
return api.s.deployOwnerTokenEstimate(ctx, chainID, fromAddress, ownerTokenParameters, masterTokenParameters, communityID, signerPubKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) EstimateMintTokens(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (*CommunityTokenFees, error) {
|
|
||||||
return api.s.mintTokensEstimate(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is only ERC721 function
|
|
||||||
func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, tokenIds []*bigint.BigInt) (*CommunityTokenFees, error) {
|
|
||||||
return api.s.remoteBurnEstimate(ctx, chainID, contractAddress, fromAddress, tokenIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) EstimateBurn(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, burnAmount *bigint.BigInt) (*CommunityTokenFees, error) {
|
|
||||||
return api.s.burnEstimate(ctx, chainID, contractAddress, fromAddress, burnAmount)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) EstimateSetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, newSignerPubKey string) (*CommunityTokenFees, error) {
|
|
||||||
return api.s.setSignerPubKeyEstimate(ctx, chainID, contractAddress, fromAddress, newSignerPubKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) NewOwnerTokenInstance(chainID uint64, contractAddress string) (*ownertoken.OwnerToken, error) {
|
|
||||||
return api.s.NewOwnerTokenInstance(chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) NewCommunityTokenDeployerInstance(chainID uint64) (*communitytokendeployer.CommunityTokenDeployer, error) {
|
|
||||||
return api.s.manager.NewCommunityTokenDeployerInstance(chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) NewCommunityOwnerTokenRegistryInstance(chainID uint64, contractAddress string) (*communityownertokenregistry.CommunityOwnerTokenRegistry, error) {
|
|
||||||
return api.s.NewCommunityOwnerTokenRegistryInstance(chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) NewCollectiblesInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
|
||||||
return api.s.manager.NewCollectiblesInstance(chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) NewAssetsInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
|
||||||
return api.s.manager.NewAssetsInstance(chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Universal minting function for every type of token.
|
|
||||||
func (api *API) MintTokens(ctx context.Context, chainID uint64, contractAddress string, txArgs wallettypes.SendTxArgs, password string, walletAddresses []string, amount *bigint.BigInt) (string, error) {
|
|
||||||
|
|
||||||
err := api.s.ValidateWalletsAndAmounts(walletAddresses, amount)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.VerifyPasswordAndGetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
contractInst, err := NewTokenInstance(api.s, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
tx, err := contractInst.Mint(transactOpts, walletAddresses, amount)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
tx.Hash(),
|
|
||||||
common.Address(txArgs.From),
|
|
||||||
common.HexToAddress(contractAddress),
|
|
||||||
transactions.AirdropCommunityToken,
|
|
||||||
transactions.Keep,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error("TrackPendingTransaction error", zap.Error(err))
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tx.Hash().Hex(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is only ERC721 function
|
|
||||||
func (api *API) RemoteDestructedAmount(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
|
||||||
contractInst, err := api.NewCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// total supply = airdropped only (w/o burnt)
|
|
||||||
totalSupply, err := contractInst.TotalSupply(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// minted = all created tokens (airdropped and remotely destructed)
|
|
||||||
mintedCount, err := contractInst.MintedCount(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res = new(big.Int)
|
|
||||||
res.Sub(mintedCount, totalSupply)
|
|
||||||
|
|
||||||
return &bigint.BigInt{Int: res}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is only ERC721 function
|
|
||||||
func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress string, txArgs wallettypes.SendTxArgs, password string, tokenIds []*bigint.BigInt, additionalData string) (string, error) {
|
|
||||||
err := api.s.validateTokens(tokenIds)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.VerifyPasswordAndGetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
var tempTokenIds []*big.Int
|
|
||||||
for _, v := range tokenIds {
|
|
||||||
tempTokenIds = append(tempTokenIds, v.Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
contractInst, err := NewTokenInstance(api.s, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
tx, err := contractInst.RemoteBurn(transactOpts, tempTokenIds)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
tx.Hash(),
|
|
||||||
common.Address(txArgs.From),
|
|
||||||
common.HexToAddress(contractAddress),
|
|
||||||
transactions.RemoteDestructCollectible,
|
|
||||||
transactions.Keep,
|
|
||||||
additionalData,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error("TrackPendingTransaction error", zap.Error(err))
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tx.Hash().Hex(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) GetCollectiblesContractInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
|
||||||
return api.s.manager.GetCollectiblesContractInstance(chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) GetAssetContractInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
|
||||||
return api.s.manager.GetAssetContractInstance(chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) RemainingSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
|
||||||
return api.s.remainingSupply(ctx, chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) Burn(ctx context.Context, chainID uint64, contractAddress string, txArgs wallettypes.SendTxArgs, password string, burnAmount *bigint.BigInt) (string, error) {
|
|
||||||
err := api.s.validateBurnAmount(ctx, burnAmount, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.VerifyPasswordAndGetSigner(chainID, api.s.accountsManager, api.s.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
newMaxSupply, err := api.s.prepareNewMaxSupply(ctx, chainID, contractAddress, burnAmount)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
contractInst, err := NewTokenInstance(api.s, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
tx, err := contractInst.SetMaxSupply(transactOpts, newMaxSupply)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = api.s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
tx.Hash(),
|
|
||||||
common.Address(txArgs.From),
|
|
||||||
common.HexToAddress(contractAddress),
|
|
||||||
transactions.BurnCommunityToken,
|
|
||||||
transactions.Keep,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error("TrackPendingTransaction error", zap.Error(err))
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tx.Hash().Hex(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets signer public key from smart contract with a given chainId and address
|
|
||||||
func (api *API) GetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string) (string, error) {
|
|
||||||
return api.s.GetSignerPubKey(ctx, chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets signer public key directly from deployer contract
|
|
||||||
func (api *API) SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error) {
|
|
||||||
return api.s.SafeGetSignerPubKey(ctx, chainID, communityID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets owner token contract address from deployer contract
|
|
||||||
func (api *API) SafeGetOwnerTokenAddress(ctx context.Context, chainID uint64, communityID string) (string, error) {
|
|
||||||
return api.s.SafeGetOwnerTokenAddress(ctx, chainID, communityID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) SetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string, txArgs wallettypes.SendTxArgs, password string, newSignerPubKey string) (string, error) {
|
|
||||||
return api.s.SetSignerPubKey(ctx, chainID, contractAddress, txArgs, password, newSignerPubKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) OwnerTokenOwnerAddress(ctx context.Context, chainID uint64, contractAddress string) (string, error) {
|
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
|
||||||
contractInst, err := api.NewOwnerTokenInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ownerAddress, err := contractInst.OwnerOf(callOpts, big.NewInt(0))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return ownerAddress.Hex(), nil
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package communitytokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTypedDataHash(t *testing.T) {
|
|
||||||
sigHash := common.Hex2Bytes("dd91c30357aafeb2792b5f0facbd83995943c1ea113a906ebbeb58bfeb27dfc2")
|
|
||||||
domainSep := common.Hex2Bytes("4a672b5a08e88d37f7239165a0c9e03a01196587d52c638c0c99cbee5ba527c8")
|
|
||||||
contractAddr := "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
|
|
||||||
signer := "0x54e3922e97e334905fb489be7c5df1f83cb1ce58"
|
|
||||||
deployer := "0x7c8999dC9a822c1f0Df42023113EDB4FDd543266"
|
|
||||||
goodHashResult := "0xccbb375343347491706cf4b43796f7b96ccc89c9e191a8b78679daeba1684ec7"
|
|
||||||
|
|
||||||
typedHash, err := typedStructuredDataHash(domainSep, signer, deployer, contractAddr, 420)
|
|
||||||
require.NoError(t, err, "creating typed structured data hash")
|
|
||||||
require.Equal(t, goodHashResult, typedHash.String())
|
|
||||||
|
|
||||||
customTypedHash := customTypedStructuredDataHash(domainSep, sigHash, signer, deployer)
|
|
||||||
require.Equal(t, goodHashResult, customTypedHash.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompressedKeyToEthAddress(t *testing.T) {
|
|
||||||
ethAddr, err := convert33BytesPubKeyToEthAddress("0x02bcbe39785b55a22383f82ac631ea7500e204627369c4ea01d9296af0ea573f57")
|
|
||||||
require.NoError(t, err, "converting pub key to address")
|
|
||||||
require.Equal(t, "0x0A1ec0002dDB927B03049F1aD8D589aBEA4Ba4b3", ethAddr.Hex())
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
package communitytokensdatabase
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/status-im/status-go/protocol/communities/token"
|
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Database struct {
|
|
||||||
db *sql.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCommunityTokensDatabase(db *sql.DB) *Database {
|
|
||||||
return &Database{db: db}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *Database) GetTokenType(chainID uint64, contractAddress string) (protobuf.CommunityTokenType, error) {
|
|
||||||
var result = protobuf.CommunityTokenType_UNKNOWN_TOKEN_TYPE
|
|
||||||
rows, err := db.db.Query(`SELECT type FROM community_tokens WHERE chain_id=? AND address=? LIMIT 1`, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
if rows.Next() {
|
|
||||||
err := rows.Scan(&result)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
return result, fmt.Errorf("can't find token: chainId %v, contractAddress %v", chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *Database) GetTokenPrivilegesLevel(chainID uint64, contractAddress string) (token.PrivilegesLevel, error) {
|
|
||||||
var result = token.CommunityLevel
|
|
||||||
rows, err := db.db.Query(`SELECT privileges_level FROM community_tokens WHERE chain_id=? AND address=? LIMIT 1`, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
if rows.Next() {
|
|
||||||
err := rows.Scan(&result)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
return result, fmt.Errorf("can't find privileges level: chainId %v, contractAddress %v", chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *Database) GetCommunityERC20Metadata() ([]*token.CommunityToken, error) {
|
|
||||||
rows, err := db.db.Query(`SELECT community_id, address, name, symbol, chain_id FROM community_tokens WHERE type = ?`, protobuf.CommunityTokenType_ERC20)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var result []*token.CommunityToken
|
|
||||||
for rows.Next() {
|
|
||||||
token := token.CommunityToken{}
|
|
||||||
err := rows.Scan(&token.CommunityID, &token.Address, &token.Name, &token.Symbol, &token.ChainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result = append(result, &token)
|
|
||||||
}
|
|
||||||
return result, rows.Err()
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
package communitytokensdatabase
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/suite"
|
|
||||||
|
|
||||||
"github.com/status-im/status-go/appdatabase"
|
|
||||||
"github.com/status-im/status-go/protocol/communities/token"
|
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
|
||||||
"github.com/status-im/status-go/protocol/sqlite"
|
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
|
||||||
"github.com/status-im/status-go/t/helpers"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDatabaseSuite(t *testing.T) {
|
|
||||||
suite.Run(t, new(DatabaseSuite))
|
|
||||||
}
|
|
||||||
|
|
||||||
type DatabaseSuite struct {
|
|
||||||
suite.Suite
|
|
||||||
|
|
||||||
db *Database
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DatabaseSuite) addCommunityToken(db *sql.DB, token *token.CommunityToken) error {
|
|
||||||
_, err := db.Exec(`INSERT INTO community_tokens (community_id, address, type, name, symbol, description, supply_str,
|
|
||||||
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, token.CommunityID, token.Address, token.TokenType, token.Name,
|
|
||||||
token.Symbol, token.Description, token.Supply.String(), token.InfiniteSupply, token.Transferable, token.RemoteSelfDestruct,
|
|
||||||
token.ChainID, token.DeployState, token.Base64Image, token.Decimals, token.Deployer, token.PrivilegesLevel)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DatabaseSuite) setupDatabase(db *sql.DB) error {
|
|
||||||
token721 := &token.CommunityToken{
|
|
||||||
CommunityID: "123",
|
|
||||||
TokenType: protobuf.CommunityTokenType_ERC721,
|
|
||||||
Address: "0x123",
|
|
||||||
Name: "StatusToken",
|
|
||||||
Symbol: "STT",
|
|
||||||
Description: "desc",
|
|
||||||
Supply: &bigint.BigInt{Int: big.NewInt(123)},
|
|
||||||
InfiniteSupply: false,
|
|
||||||
Transferable: true,
|
|
||||||
RemoteSelfDestruct: true,
|
|
||||||
ChainID: 1,
|
|
||||||
DeployState: token.InProgress,
|
|
||||||
Base64Image: "ABCD",
|
|
||||||
Deployer: "0xDEP1",
|
|
||||||
PrivilegesLevel: token.OwnerLevel,
|
|
||||||
}
|
|
||||||
|
|
||||||
token20 := &token.CommunityToken{
|
|
||||||
CommunityID: "345",
|
|
||||||
TokenType: protobuf.CommunityTokenType_ERC20,
|
|
||||||
Address: "0x345",
|
|
||||||
Name: "StatusToken",
|
|
||||||
Symbol: "STT",
|
|
||||||
Description: "desc",
|
|
||||||
Supply: &bigint.BigInt{Int: big.NewInt(345)},
|
|
||||||
InfiniteSupply: false,
|
|
||||||
Transferable: true,
|
|
||||||
RemoteSelfDestruct: true,
|
|
||||||
ChainID: 2,
|
|
||||||
DeployState: token.Failed,
|
|
||||||
Base64Image: "QWERTY",
|
|
||||||
Decimals: 21,
|
|
||||||
Deployer: "0xDEP2",
|
|
||||||
PrivilegesLevel: token.CommunityLevel,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := s.addCommunityToken(db, token721)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.addCommunityToken(db, token20)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DatabaseSuite) SetupTest() {
|
|
||||||
s.db = nil
|
|
||||||
|
|
||||||
db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{})
|
|
||||||
s.NoError(err, "creating sqlite db instance")
|
|
||||||
|
|
||||||
err = sqlite.Migrate(db)
|
|
||||||
s.NoError(err, "protocol migrate")
|
|
||||||
|
|
||||||
s.db = &Database{db: db}
|
|
||||||
|
|
||||||
err = s.setupDatabase(db)
|
|
||||||
s.NoError(err, "setting up database")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DatabaseSuite) TestGetTokenType() {
|
|
||||||
contractType, err := s.db.GetTokenType(1, "0x123")
|
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Equal(contractType, protobuf.CommunityTokenType_ERC721)
|
|
||||||
|
|
||||||
contractType, err = s.db.GetTokenType(2, "0x345")
|
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Equal(contractType, protobuf.CommunityTokenType_ERC20)
|
|
||||||
|
|
||||||
_, err = s.db.GetTokenType(10, "0x777")
|
|
||||||
s.Require().Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DatabaseSuite) TestGetPrivilegesLevel() {
|
|
||||||
privLevel, err := s.db.GetTokenPrivilegesLevel(1, "0x123")
|
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Equal(privLevel, token.OwnerLevel)
|
|
||||||
|
|
||||||
privLevel, err = s.db.GetTokenPrivilegesLevel(2, "0x345")
|
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Equal(privLevel, token.CommunityLevel)
|
|
||||||
|
|
||||||
_, err = s.db.GetTokenType(10, "0x777")
|
|
||||||
s.Require().Error(err)
|
|
||||||
}
|
|
@ -1,443 +0,0 @@
|
|||||||
package communitytokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/assets"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/collectibles"
|
|
||||||
communitytokendeployer "github.com/status-im/status-go/contracts/community-tokens/deployer"
|
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
|
||||||
"github.com/status-im/status-go/logutils"
|
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
|
||||||
"github.com/status-im/status-go/services/wallet/requests"
|
|
||||||
"github.com/status-im/status-go/services/wallet/router/fees"
|
|
||||||
"github.com/status-im/status-go/services/wallet/wallettypes"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CommunityTokenFees struct {
|
|
||||||
GasUnits uint64 `json:"gasUnits"`
|
|
||||||
SuggestedFees *fees.SuggestedFeesGwei `json:"suggestedFees"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func weiToGwei(val *big.Int) *big.Float {
|
|
||||||
result := new(big.Float)
|
|
||||||
result.SetInt(val)
|
|
||||||
|
|
||||||
unit := new(big.Int)
|
|
||||||
unit.SetInt64(params.GWei)
|
|
||||||
|
|
||||||
return result.Quo(result, new(big.Float).SetInt(unit))
|
|
||||||
}
|
|
||||||
|
|
||||||
func gweiToWei(val *big.Float) *big.Int {
|
|
||||||
res, _ := new(big.Float).Mul(val, big.NewFloat(1000000000)).Int(nil)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) deployOwnerTokenEstimate(ctx context.Context, chainID uint64, fromAddress string,
|
|
||||||
ownerTokenParameters requests.DeploymentParameters, masterTokenParameters requests.DeploymentParameters,
|
|
||||||
communityID string, signerPubKey string) (*CommunityTokenFees, error) {
|
|
||||||
|
|
||||||
gasUnits, err := s.deployOwnerTokenGasUnits(ctx, chainID, fromAddress, ownerTokenParameters, masterTokenParameters,
|
|
||||||
communityID, signerPubKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
deployerAddress, err := communitytokendeployer.ContractAddress(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.prepareCommunityTokenFees(ctx, common.HexToAddress(fromAddress), &deployerAddress, gasUnits, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) deployCollectiblesEstimate(ctx context.Context, chainID uint64, fromAddress string) (*CommunityTokenFees, error) {
|
|
||||||
gasUnits, err := s.deployCollectiblesGasUnits(ctx, chainID, fromAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s.prepareCommunityTokenFees(ctx, common.HexToAddress(fromAddress), nil, gasUnits, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) deployAssetsEstimate(ctx context.Context, chainID uint64, fromAddress string) (*CommunityTokenFees, error) {
|
|
||||||
gasUnits, err := s.deployAssetsGasUnits(ctx, chainID, fromAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s.prepareCommunityTokenFees(ctx, common.HexToAddress(fromAddress), nil, gasUnits, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) mintTokensEstimate(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (*CommunityTokenFees, error) {
|
|
||||||
gasUnits, err := s.mintTokensGasUnits(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
toAddress := common.HexToAddress(contractAddress)
|
|
||||||
return s.prepareCommunityTokenFees(ctx, common.HexToAddress(fromAddress), &toAddress, gasUnits, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) remoteBurnEstimate(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, tokenIds []*bigint.BigInt) (*CommunityTokenFees, error) {
|
|
||||||
gasUnits, err := s.remoteBurnGasUnits(ctx, chainID, contractAddress, fromAddress, tokenIds)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
toAddress := common.HexToAddress(contractAddress)
|
|
||||||
return s.prepareCommunityTokenFees(ctx, common.HexToAddress(fromAddress), &toAddress, gasUnits, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) burnEstimate(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, burnAmount *bigint.BigInt) (*CommunityTokenFees, error) {
|
|
||||||
gasUnits, err := s.burnGasUnits(ctx, chainID, contractAddress, fromAddress, burnAmount)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
toAddress := common.HexToAddress(contractAddress)
|
|
||||||
return s.prepareCommunityTokenFees(ctx, common.HexToAddress(fromAddress), &toAddress, gasUnits, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) setSignerPubKeyEstimate(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, newSignerPubKey string) (*CommunityTokenFees, error) {
|
|
||||||
gasUnits, err := s.setSignerPubKeyGasUnits(ctx, chainID, contractAddress, fromAddress, newSignerPubKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
toAddress := common.HexToAddress(contractAddress)
|
|
||||||
return s.prepareCommunityTokenFees(ctx, common.HexToAddress(fromAddress), &toAddress, gasUnits, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) setSignerPubKeyGasUnits(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, newSignerPubKey string) (uint64, error) {
|
|
||||||
if len(newSignerPubKey) <= 0 {
|
|
||||||
return 0, fmt.Errorf("signerPubKey is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
contractInst, err := s.NewOwnerTokenInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
ownerTokenInstance := &OwnerTokenInstance{instance: contractInst}
|
|
||||||
|
|
||||||
return s.estimateMethodForTokenInstance(ctx, ownerTokenInstance, chainID, contractAddress, fromAddress, "setSignerPublicKey", common.FromHex(newSignerPubKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) burnGasUnits(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, burnAmount *bigint.BigInt) (uint64, error) {
|
|
||||||
err := s.validateBurnAmount(ctx, burnAmount, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
newMaxSupply, err := s.prepareNewMaxSupply(ctx, chainID, contractAddress, burnAmount)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.estimateMethod(ctx, chainID, contractAddress, fromAddress, "setMaxSupply", newMaxSupply)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) remoteBurnGasUnits(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, tokenIds []*bigint.BigInt) (uint64, error) {
|
|
||||||
err := s.validateTokens(tokenIds)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var tempTokenIds []*big.Int
|
|
||||||
for _, v := range tokenIds {
|
|
||||||
tempTokenIds = append(tempTokenIds, v.Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.estimateMethod(ctx, chainID, contractAddress, fromAddress, "remoteBurn", tempTokenIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) deployOwnerTokenGasUnits(ctx context.Context, chainID uint64, fromAddress string,
|
|
||||||
ownerTokenParameters requests.DeploymentParameters, masterTokenParameters requests.DeploymentParameters,
|
|
||||||
communityID string, signerPubKey string) (uint64, error) {
|
|
||||||
ethClient, err := s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
deployerAddress, err := communitytokendeployer.ContractAddress(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
deployerABI, err := abi.JSON(strings.NewReader(communitytokendeployer.CommunityTokenDeployerABI))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ownerTokenConfig := communitytokendeployer.CommunityTokenDeployerTokenConfig{
|
|
||||||
Name: ownerTokenParameters.Name,
|
|
||||||
Symbol: ownerTokenParameters.Symbol,
|
|
||||||
BaseURI: ownerTokenParameters.TokenURI,
|
|
||||||
}
|
|
||||||
|
|
||||||
masterTokenConfig := communitytokendeployer.CommunityTokenDeployerTokenConfig{
|
|
||||||
Name: masterTokenParameters.Name,
|
|
||||||
Symbol: masterTokenParameters.Symbol,
|
|
||||||
BaseURI: masterTokenParameters.TokenURI,
|
|
||||||
}
|
|
||||||
|
|
||||||
signature, err := 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
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := deployerABI.Pack("deploy", ownerTokenConfig, masterTokenConfig, communitySignature, common.FromHex(signerPubKey))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
toAddr := deployerAddress
|
|
||||||
fromAddr := common.HexToAddress(fromAddress)
|
|
||||||
|
|
||||||
callMsg := ethereum.CallMsg{
|
|
||||||
From: fromAddr,
|
|
||||||
To: &toAddr,
|
|
||||||
Value: big.NewInt(0),
|
|
||||||
Data: data,
|
|
||||||
}
|
|
||||||
|
|
||||||
estimate, err := ethClient.EstimateGas(ctx, callMsg)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
finalEstimation := estimate + uint64(float32(estimate)*0.1)
|
|
||||||
logutils.ZapLogger().Debug("Owner token deployment estimation", zap.Uint64("gas", finalEstimation))
|
|
||||||
return finalEstimation, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) deployCollectiblesGasUnits(ctx context.Context, chainID uint64, fromAddress string) (uint64, error) {
|
|
||||||
ethClient, err := s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
collectiblesABI, err := abi.JSON(strings.NewReader(collectibles.CollectiblesABI))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// use random parameters, they will not have impact on deployment results
|
|
||||||
data, err := collectiblesABI.Pack("" /*constructor name is empty*/, "name", "SYMBOL", big.NewInt(20), true, false, "tokenUri",
|
|
||||||
common.HexToAddress("0x77b48394c650520012795a1a25696d7eb542d110"), common.HexToAddress("0x77b48394c650520012795a1a25696d7eb542d110"))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
callMsg := ethereum.CallMsg{
|
|
||||||
From: common.HexToAddress(fromAddress),
|
|
||||||
To: nil,
|
|
||||||
Value: big.NewInt(0),
|
|
||||||
Data: append(common.FromHex(collectibles.CollectiblesBin), data...),
|
|
||||||
}
|
|
||||||
estimate, err := ethClient.EstimateGas(ctx, callMsg)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
finalEstimation := estimate + uint64(float32(estimate)*0.1)
|
|
||||||
logutils.ZapLogger().Debug("Collectibles deployment estimation", zap.Uint64("gas", finalEstimation))
|
|
||||||
return finalEstimation, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) deployAssetsGasUnits(ctx context.Context, chainID uint64, fromAddress string) (uint64, error) {
|
|
||||||
ethClient, err := s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
assetsABI, err := abi.JSON(strings.NewReader(assets.AssetsABI))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// use random parameters, they will not have impact on deployment results
|
|
||||||
data, err := assetsABI.Pack("" /*constructor name is empty*/, "name", "SYMBOL", uint8(18), big.NewInt(20), "tokenUri",
|
|
||||||
common.HexToAddress("0x77b48394c650520012795a1a25696d7eb542d110"), common.HexToAddress("0x77b48394c650520012795a1a25696d7eb542d110"))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
callMsg := ethereum.CallMsg{
|
|
||||||
From: common.HexToAddress(fromAddress),
|
|
||||||
To: nil,
|
|
||||||
Value: big.NewInt(0),
|
|
||||||
Data: append(common.FromHex(assets.AssetsBin), data...),
|
|
||||||
}
|
|
||||||
estimate, err := ethClient.EstimateGas(ctx, callMsg)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
finalEstimation := estimate + uint64(float32(estimate)*0.1)
|
|
||||||
logutils.ZapLogger().Debug("Assets deployment estimation: ", zap.Uint64("gas", finalEstimation))
|
|
||||||
return finalEstimation, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we want to mint 2 tokens to addresses ["a", "b"] we need to mint
|
|
||||||
// twice to every address - we need to send to smart contract table ["a", "a", "b", "b"]
|
|
||||||
func multiplyWalletAddresses(amount *bigint.BigInt, contractAddresses []string) []string {
|
|
||||||
var totalAddresses []string
|
|
||||||
for i := big.NewInt(1); i.Cmp(amount.Int) <= 0; {
|
|
||||||
totalAddresses = append(totalAddresses, contractAddresses...)
|
|
||||||
i.Add(i, big.NewInt(1))
|
|
||||||
}
|
|
||||||
return totalAddresses
|
|
||||||
}
|
|
||||||
|
|
||||||
func prepareMintCollectiblesData(walletAddresses []string, amount *bigint.BigInt) []common.Address {
|
|
||||||
totalAddresses := multiplyWalletAddresses(amount, walletAddresses)
|
|
||||||
var usersAddresses = []common.Address{}
|
|
||||||
for _, k := range totalAddresses {
|
|
||||||
usersAddresses = append(usersAddresses, common.HexToAddress(k))
|
|
||||||
}
|
|
||||||
return usersAddresses
|
|
||||||
}
|
|
||||||
|
|
||||||
func prepareMintAssetsData(walletAddresses []string, amount *bigint.BigInt) ([]common.Address, []*big.Int) {
|
|
||||||
var usersAddresses = []common.Address{}
|
|
||||||
var amountsList = []*big.Int{}
|
|
||||||
for _, k := range walletAddresses {
|
|
||||||
usersAddresses = append(usersAddresses, common.HexToAddress(k))
|
|
||||||
amountsList = append(amountsList, amount.Int)
|
|
||||||
}
|
|
||||||
return usersAddresses, amountsList
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) mintCollectiblesGasUnits(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
|
||||||
err := s.ValidateWalletsAndAmounts(walletAddresses, amount)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
usersAddresses := prepareMintCollectiblesData(walletAddresses, amount)
|
|
||||||
return s.estimateMethod(ctx, chainID, contractAddress, fromAddress, "mintTo", usersAddresses)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) mintAssetsGasUnits(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
|
||||||
err := s.ValidateWalletsAndAmounts(walletAddresses, amount)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
usersAddresses, amountsList := prepareMintAssetsData(walletAddresses, amount)
|
|
||||||
return s.estimateMethod(ctx, chainID, contractAddress, fromAddress, "mintTo", usersAddresses, amountsList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) mintTokensGasUnits(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
|
||||||
tokenType, err := s.db.GetTokenType(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tokenType {
|
|
||||||
case protobuf.CommunityTokenType_ERC721:
|
|
||||||
return s.mintCollectiblesGasUnits(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
|
||||||
case protobuf.CommunityTokenType_ERC20:
|
|
||||||
return s.mintAssetsGasUnits(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
|
||||||
default:
|
|
||||||
return 0, fmt.Errorf("unknown token type: %v", tokenType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) prepareCommunityTokenFees(ctx context.Context, from common.Address, to *common.Address, gasUnits uint64, chainID uint64) (*CommunityTokenFees, error) {
|
|
||||||
suggestedFees, err := s.feeManager.SuggestedFeesGwei(ctx, chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
txArgs := s.suggestedFeesToSendTxArgs(from, to, gasUnits, suggestedFees)
|
|
||||||
|
|
||||||
l1Fee, err := s.estimateL1Fee(ctx, chainID, txArgs)
|
|
||||||
if err == nil {
|
|
||||||
suggestedFees.L1GasFee = weiToGwei(big.NewInt(int64(l1Fee)))
|
|
||||||
}
|
|
||||||
return &CommunityTokenFees{
|
|
||||||
GasUnits: gasUnits,
|
|
||||||
SuggestedFees: suggestedFees,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) suggestedFeesToSendTxArgs(from common.Address, to *common.Address, gas uint64, suggestedFees *fees.SuggestedFeesGwei) wallettypes.SendTxArgs {
|
|
||||||
sendArgs := wallettypes.SendTxArgs{}
|
|
||||||
sendArgs.From = types.Address(from)
|
|
||||||
sendArgs.To = (*types.Address)(to)
|
|
||||||
sendArgs.Gas = (*hexutil.Uint64)(&gas)
|
|
||||||
if suggestedFees.EIP1559Enabled {
|
|
||||||
sendArgs.MaxPriorityFeePerGas = (*hexutil.Big)(gweiToWei(suggestedFees.MaxPriorityFeePerGas))
|
|
||||||
sendArgs.MaxFeePerGas = (*hexutil.Big)(gweiToWei(suggestedFees.MaxFeePerGasMedium))
|
|
||||||
} else {
|
|
||||||
sendArgs.GasPrice = (*hexutil.Big)(gweiToWei(suggestedFees.GasPrice))
|
|
||||||
}
|
|
||||||
return sendArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) estimateL1Fee(ctx context.Context, chainID uint64, sendArgs wallettypes.SendTxArgs) (uint64, error) {
|
|
||||||
transaction, _, err := s.transactor.ValidateAndBuildTransaction(chainID, sendArgs, -1)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := transaction.MarshalBinary()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.feeManager.GetL1Fee(ctx, chainID, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) estimateMethodForTokenInstance(ctx context.Context, contractInstance TokenInstance, chainID uint64, contractAddress string, fromAddress string, methodName string, args ...interface{}) (uint64, error) {
|
|
||||||
ethClient, err := s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error(err.Error())
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := contractInstance.PackMethod(ctx, methodName, args...)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
toAddr := common.HexToAddress(contractAddress)
|
|
||||||
fromAddr := common.HexToAddress(fromAddress)
|
|
||||||
|
|
||||||
callMsg := ethereum.CallMsg{
|
|
||||||
From: fromAddr,
|
|
||||||
To: &toAddr,
|
|
||||||
Value: big.NewInt(0),
|
|
||||||
Data: data,
|
|
||||||
}
|
|
||||||
estimate, err := ethClient.EstimateGas(ctx, callMsg)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return estimate + uint64(float32(estimate)*0.1), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) estimateMethod(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, methodName string, args ...interface{}) (uint64, error) {
|
|
||||||
contractInst, err := NewTokenInstance(s, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return s.estimateMethodForTokenInstance(ctx, contractInst, chainID, contractAddress, fromAddress, methodName, args...)
|
|
||||||
}
|
|
@ -1,210 +0,0 @@
|
|||||||
package communitytokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/assets"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/collectibles"
|
|
||||||
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"
|
|
||||||
"github.com/status-im/status-go/services/wallet/requests"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Manager struct {
|
|
||||||
rpcClient *rpc.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewManager(rpcClient *rpc.Client) *Manager {
|
|
||||||
return &Manager{
|
|
||||||
rpcClient: rpcClient,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) NewCollectiblesInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
|
||||||
backend, err := m.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return collectibles.NewCollectibles(common.HexToAddress(contractAddress), backend)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) NewCommunityTokenDeployerInstance(chainID uint64) (*communitytokendeployer.CommunityTokenDeployer, error) {
|
|
||||||
backend, err := m.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
deployerAddr, err := communitytokendeployer.ContractAddress(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return communitytokendeployer.NewCommunityTokenDeployer(deployerAddr, backend)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) GetCollectiblesContractInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
|
||||||
contractInst, err := m.NewCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return contractInst, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) NewAssetsInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
|
||||||
backend, err := m.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return assets.NewAssets(common.HexToAddress(contractAddress), backend)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) GetAssetContractInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
|
||||||
contractInst, err := m.NewAssetsInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return contractInst, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
totalSupply, err := contract.MaxSupply(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
transferable, err := contract.Transferable(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
remoteBurnable, err := contract.RemoteBurnable(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &communities.CollectibleContractData{
|
|
||||||
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
|
||||||
Transferable: transferable,
|
|
||||||
RemoteBurnable: remoteBurnable,
|
|
||||||
InfiniteSupply: requests.GetInfiniteSupply().Cmp(totalSupply) == 0,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
totalSupply, err := contract.MaxSupply(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &communities.AssetContractData{
|
|
||||||
TotalSupply: &bigint.BigInt{Int: totalSupply},
|
|
||||||
InfiniteSupply: requests.GetInfiniteSupply().Cmp(totalSupply) == 0,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func convert33BytesPubKeyToEthAddress(pubKey string) (common.Address, error) {
|
|
||||||
decoded, err := types.DecodeHex(pubKey)
|
|
||||||
if err != nil {
|
|
||||||
return common.Address{}, err
|
|
||||||
}
|
|
||||||
communityPubKey, err := crypto.DecompressPubkey(decoded)
|
|
||||||
if err != nil {
|
|
||||||
return common.Address{}, err
|
|
||||||
}
|
|
||||||
return common.Address(crypto.PubkeyToAddress(*communityPubKey)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simpler version of hashing typed structured data alternative to typedStructuredDataHash. Keeping this for reference.
|
|
||||||
func customTypedStructuredDataHash(domainSeparator []byte, signatureTypedHash []byte, signer string, deployer string) types.Hash {
|
|
||||||
// every field should be 32 bytes, eth address is 20 bytes so padding should be added
|
|
||||||
emptyOffset := [12]byte{}
|
|
||||||
hashedEncoded := crypto.Keccak256Hash(signatureTypedHash, emptyOffset[:], common.HexToAddress(signer).Bytes(),
|
|
||||||
emptyOffset[:], common.HexToAddress(deployer).Bytes())
|
|
||||||
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", domainSeparator, hashedEncoded.Bytes()))
|
|
||||||
return crypto.Keccak256Hash(rawData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a typed structured hash according to https://eips.ethereum.org/EIPS/eip-712
|
|
||||||
// Domain separator from smart contract is used.
|
|
||||||
func typedStructuredDataHash(domainSeparator []byte, signer string, addressFrom string, deployerContractAddress string, chainID uint64) (types.Hash, error) {
|
|
||||||
myTypedData := apitypes.TypedData{
|
|
||||||
Types: apitypes.Types{
|
|
||||||
"Deploy": []apitypes.Type{
|
|
||||||
{Name: "signer", Type: "address"},
|
|
||||||
{Name: "deployer", Type: "address"},
|
|
||||||
},
|
|
||||||
"EIP712Domain": []apitypes.Type{
|
|
||||||
{Name: "name", Type: "string"},
|
|
||||||
{Name: "version", Type: "string"},
|
|
||||||
{Name: "chainId", Type: "uint256"},
|
|
||||||
{Name: "verifyingContract", Type: "address"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PrimaryType: "Deploy",
|
|
||||||
// Domain field should be here to keep correct structure but
|
|
||||||
// domainSeparator from smart contract is used.
|
|
||||||
Domain: apitypes.TypedDataDomain{
|
|
||||||
Name: "CommunityTokenDeployer", // name from Deployer smart contract
|
|
||||||
Version: "1", // version from Deployer smart contract
|
|
||||||
ChainId: math.NewHexOrDecimal256(int64(chainID)),
|
|
||||||
VerifyingContract: deployerContractAddress,
|
|
||||||
},
|
|
||||||
Message: apitypes.TypedDataMessage{
|
|
||||||
"signer": signer,
|
|
||||||
"deployer": addressFrom,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
typedDataHash, err := myTypedData.HashStruct(myTypedData.PrimaryType, myTypedData.Message)
|
|
||||||
if err != nil {
|
|
||||||
return types.Hash{}, err
|
|
||||||
}
|
|
||||||
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", domainSeparator, string(typedDataHash)))
|
|
||||||
return crypto.Keccak256Hash(rawData), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates
|
|
||||||
func (m *Manager) DeploymentSignatureDigest(chainID uint64, addressFrom string, communityID string) ([]byte, error) {
|
|
||||||
callOpts := &bind.CallOpts{Pending: false}
|
|
||||||
communityEthAddr, err := convert33BytesPubKeyToEthAddress(communityID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
deployerAddr, err := communitytokendeployer.ContractAddress(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
deployerContractInst, err := m.NewCommunityTokenDeployerInstance(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainSeparator, err := deployerContractInst.DOMAINSEPARATOR(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
structedHash, err := typedStructuredDataHash(domainSeparator[:], communityEthAddr.Hex(), addressFrom, deployerAddr.Hex(), chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return structedHash.Bytes(), nil
|
|
||||||
}
|
|
@ -1,742 +0,0 @@
|
|||||||
package communitytokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"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/p2p"
|
|
||||||
ethRpc "github.com/ethereum/go-ethereum/rpc"
|
|
||||||
"github.com/status-im/status-go/account"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/mastertoken"
|
|
||||||
"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/logutils"
|
|
||||||
"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/requests"
|
|
||||||
"github.com/status-im/status-go/services/wallet/router/fees"
|
|
||||||
"github.com/status-im/status-go/services/wallet/walletevent"
|
|
||||||
"github.com/status-im/status-go/services/wallet/wallettypes"
|
|
||||||
"github.com/status-im/status-go/signal"
|
|
||||||
"github.com/status-im/status-go/transactions"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Collectibles service
|
|
||||||
type Service struct {
|
|
||||||
manager *Manager
|
|
||||||
accountsManager *account.GethManager
|
|
||||||
pendingTracker *transactions.PendingTxTracker
|
|
||||||
config *params.NodeConfig
|
|
||||||
db *communitytokensdatabase.Database
|
|
||||||
Messenger *protocol.Messenger
|
|
||||||
walletFeed *event.Feed
|
|
||||||
walletWatcher *walletevent.Watcher
|
|
||||||
transactor *transactions.Transactor
|
|
||||||
feeManager *fees.FeeManager
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a new Collectibles Service.
|
|
||||||
func NewService(rpcClient *rpc.Client, accountsManager *account.GethManager, pendingTracker *transactions.PendingTxTracker,
|
|
||||||
config *params.NodeConfig, appDb *sql.DB, walletFeed *event.Feed, transactor *transactions.Transactor) *Service {
|
|
||||||
return &Service{
|
|
||||||
manager: &Manager{rpcClient: rpcClient},
|
|
||||||
accountsManager: accountsManager,
|
|
||||||
pendingTracker: pendingTracker,
|
|
||||||
config: config,
|
|
||||||
db: communitytokensdatabase.NewCommunityTokensDatabase(appDb),
|
|
||||||
walletFeed: walletFeed,
|
|
||||||
transactor: transactor,
|
|
||||||
feeManager: &fees.FeeManager{RPCClient: rpcClient},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protocols returns a new protocols list. In this case, there are none.
|
|
||||||
func (s *Service) Protocols() []p2p.Protocol {
|
|
||||||
return []p2p.Protocol{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIs returns a list of new APIs.
|
|
||||||
func (s *Service) APIs() []ethRpc.API {
|
|
||||||
return []ethRpc.API{
|
|
||||||
{
|
|
||||||
Namespace: "communitytokens",
|
|
||||||
Version: "0.1.0",
|
|
||||||
Service: NewAPI(s),
|
|
||||||
Public: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
logutils.ZapLogger().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 {
|
|
||||||
logutils.ZapLogger().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 {
|
|
||||||
logutils.ZapLogger().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(0, p.Status == transactions.Success, pendingTransaction.Hash,
|
|
||||||
communityToken, ownerToken, masterToken, errorStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) handleAirdropCommunityToken(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, error) {
|
|
||||||
communityToken, err := s.Messenger.GetCommunityTokenByChainAndAddress(int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
|
||||||
if communityToken == nil {
|
|
||||||
return nil, fmt.Errorf("token does not exist in database: chainId=%v, address=%v", pendingTransaction.ChainID, pendingTransaction.To.String())
|
|
||||||
} else {
|
|
||||||
publishErr := s.publishTokenActionToPrivilegedMembers(communityToken.CommunityID, uint64(communityToken.ChainID),
|
|
||||||
communityToken.Address, protobuf.CommunityTokenAction_AIRDROP)
|
|
||||||
if publishErr != nil {
|
|
||||||
logutils.ZapLogger().Warn("can't publish airdrop action")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return communityToken, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) handleRemoteDestructCollectible(status string, pendingTransaction *transactions.PendingTransaction) (*token.CommunityToken, error) {
|
|
||||||
communityToken, err := s.Messenger.GetCommunityTokenByChainAndAddress(int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
|
||||||
if communityToken == nil {
|
|
||||||
return nil, fmt.Errorf("token does not exist in database: chainId=%v, address=%v", pendingTransaction.ChainID, pendingTransaction.To.String())
|
|
||||||
} else {
|
|
||||||
publishErr := s.publishTokenActionToPrivilegedMembers(communityToken.CommunityID, uint64(communityToken.ChainID),
|
|
||||||
communityToken.Address, protobuf.CommunityTokenAction_REMOTE_DESTRUCT)
|
|
||||||
if publishErr != nil {
|
|
||||||
logutils.ZapLogger().Warn("can't publish remote destruct action")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return communityToken, err
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
communityToken, err := s.Messenger.GetCommunityTokenByChainAndAddress(int(pendingTransaction.ChainID), pendingTransaction.To.String())
|
|
||||||
|
|
||||||
if communityToken == nil {
|
|
||||||
return nil, fmt.Errorf("token does not exist in database: chainId=%v, address=%v", pendingTransaction.ChainID, pendingTransaction.To.String())
|
|
||||||
} else {
|
|
||||||
publishErr := s.publishTokenActionToPrivilegedMembers(communityToken.CommunityID, uint64(communityToken.ChainID),
|
|
||||||
communityToken.Address, protobuf.CommunityTokenAction_BURN)
|
|
||||||
if publishErr != nil {
|
|
||||||
logutils.ZapLogger().Warn("can't publish burn action")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return communityToken, err
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return communityownertokenregistry.NewCommunityOwnerTokenRegistry(common.HexToAddress(contractAddress), backend)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) NewOwnerTokenInstance(chainID uint64, contractAddress string) (*ownertoken.OwnerToken, error) {
|
|
||||||
|
|
||||||
backend, err := s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ownertoken.NewOwnerToken(common.HexToAddress(contractAddress), backend)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) NewMasterTokenInstance(chainID uint64, contractAddress string) (*mastertoken.MasterToken, error) {
|
|
||||||
backend, err := s.manager.rpcClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return mastertoken.NewMasterToken(common.HexToAddress(contractAddress), backend)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) validateTokens(tokenIds []*bigint.BigInt) error {
|
|
||||||
if len(tokenIds) == 0 {
|
|
||||||
return errors.New("token list is empty")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) validateBurnAmount(ctx context.Context, burnAmount *bigint.BigInt, chainID uint64, contractAddress string) error {
|
|
||||||
if burnAmount.Cmp(big.NewInt(0)) <= 0 {
|
|
||||||
return errors.New("burnAmount is less than 0")
|
|
||||||
}
|
|
||||||
remainingSupply, err := s.remainingSupply(ctx, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if burnAmount.Cmp(remainingSupply.Int) > 1 {
|
|
||||||
return errors.New("burnAmount is bigger than remaining amount")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) remainingSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
|
||||||
tokenType, err := s.db.GetTokenType(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch tokenType {
|
|
||||||
case protobuf.CommunityTokenType_ERC721:
|
|
||||||
return s.remainingCollectiblesSupply(ctx, chainID, contractAddress)
|
|
||||||
case protobuf.CommunityTokenType_ERC20:
|
|
||||||
return s.remainingAssetsSupply(ctx, chainID, contractAddress)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown token type: %v", tokenType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) prepareNewMaxSupply(ctx context.Context, chainID uint64, contractAddress string, burnAmount *bigint.BigInt) (*big.Int, error) {
|
|
||||||
maxSupply, err := s.maxSupply(ctx, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var newMaxSupply = new(big.Int)
|
|
||||||
newMaxSupply.Sub(maxSupply, burnAmount.Int)
|
|
||||||
return newMaxSupply, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemainingSupply = MaxSupply - MintedCount
|
|
||||||
func (s *Service) remainingCollectiblesSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
|
||||||
contractInst, err := s.manager.NewCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
maxSupply, err := contractInst.MaxSupply(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
mintedCount, err := contractInst.MintedCount(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var res = new(big.Int)
|
|
||||||
res.Sub(maxSupply, mintedCount)
|
|
||||||
return &bigint.BigInt{Int: res}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemainingSupply = MaxSupply - TotalSupply
|
|
||||||
func (s *Service) remainingAssetsSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
|
||||||
contractInst, err := s.manager.NewAssetsInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
maxSupply, err := contractInst.MaxSupply(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
totalSupply, err := contractInst.TotalSupply(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var res = new(big.Int)
|
|
||||||
res.Sub(maxSupply, totalSupply)
|
|
||||||
return &bigint.BigInt{Int: res}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) ValidateWalletsAndAmounts(walletAddresses []string, amount *bigint.BigInt) error {
|
|
||||||
if len(walletAddresses) == 0 {
|
|
||||||
return errors.New("wallet addresses list is empty")
|
|
||||||
}
|
|
||||||
if amount.Cmp(big.NewInt(0)) <= 0 {
|
|
||||||
return errors.New("amount is <= 0")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) GetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string) (string, error) {
|
|
||||||
|
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
|
||||||
contractInst, err := s.NewOwnerTokenInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
signerPubKey, err := contractInst.SignerPublicKey(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return types.ToHex(signerPubKey), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) SafeGetSignerPubKey(ctx context.Context, chainID uint64, communityID string) (string, error) {
|
|
||||||
// 1. Get Owner Token contract address from deployer contract - SafeGetOwnerTokenAddress()
|
|
||||||
ownerTokenAddr, err := s.SafeGetOwnerTokenAddress(ctx, chainID, communityID)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
// 2. Get Signer from owner token contract - GetSignerPubKey()
|
|
||||||
return s.GetSignerPubKey(ctx, chainID, ownerTokenAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) SafeGetOwnerTokenAddress(ctx context.Context, chainID uint64, communityID string) (string, error) {
|
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
|
||||||
deployerContractInst, err := s.manager.NewCommunityTokenDeployerInstance(chainID)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
registryAddr, err := deployerContractInst.DeploymentRegistry(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
registryContractInst, err := s.NewCommunityOwnerTokenRegistryInstance(chainID, registryAddr.Hex())
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
communityEthAddress, err := convert33BytesPubKeyToEthAddress(communityID)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ownerTokenAddress, err := registryContractInst.GetEntry(callOpts, communityEthAddress)
|
|
||||||
|
|
||||||
return ownerTokenAddress.Hex(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
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) (*communities.AssetContractData, error) {
|
|
||||||
return s.manager.GetAssetContractData(chainID, contractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) DeploymentSignatureDigest(chainID uint64, addressFrom string, communityID string) ([]byte, error) {
|
|
||||||
return s.manager.DeploymentSignatureDigest(chainID, addressFrom, communityID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) ProcessCommunityTokenAction(message *protobuf.CommunityTokenAction) error {
|
|
||||||
communityToken, err := s.Messenger.GetCommunityTokenByChainAndAddress(int(message.ChainId), message.ContractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if communityToken == nil {
|
|
||||||
return fmt.Errorf("can't find community token in database: chain %v, address %v", message.ChainId, message.ContractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
if message.ActionType == protobuf.CommunityTokenAction_BURN {
|
|
||||||
// get new max supply and update database
|
|
||||||
newMaxSupply, err := s.maxSupply(context.Background(), uint64(communityToken.ChainID), communityToken.Address)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = s.Messenger.UpdateCommunityTokenSupply(communityToken.ChainID, communityToken.Address, &bigint.BigInt{Int: newMaxSupply})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
communityToken, _ = s.Messenger.GetCommunityTokenByChainAndAddress(int(message.ChainId), message.ContractAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
signal.SendCommunityTokenActionSignal(communityToken, message.ActionType)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) SetSignerPubKey(ctx context.Context, chainID uint64, contractAddress string, txArgs wallettypes.SendTxArgs, password string, newSignerPubKey string) (string, error) {
|
|
||||||
|
|
||||||
if len(newSignerPubKey) <= 0 {
|
|
||||||
return "", fmt.Errorf("signerPubKey is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.VerifyPasswordAndGetSigner(chainID, s.accountsManager, s.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
contractInst, err := s.NewOwnerTokenInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
tx, err := contractInst.SetSignerPublicKey(transactOpts, common.FromHex(newSignerPubKey))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
tx.Hash(),
|
|
||||||
common.Address(txArgs.From),
|
|
||||||
common.HexToAddress(contractAddress),
|
|
||||||
transactions.SetSignerPublicKey,
|
|
||||||
transactions.Keep,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logutils.ZapLogger().Error("TrackPendingTransaction error", zap.Error(err))
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
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 requests.DeploymentParameters,
|
|
||||||
deployerAddress string, contractAddress string, tokenType protobuf.CommunityTokenType, privilegesLevel token.PrivilegesLevel, transactionHash string) (*token.CommunityToken, error) {
|
|
||||||
|
|
||||||
contractVersion := ""
|
|
||||||
if privilegesLevel == token.CommunityLevel {
|
|
||||||
contractVersion = s.currentVersion()
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
TransactionHash: transactionHash,
|
|
||||||
Version: contractVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.Messenger.SaveCommunityToken(tokenToSave, deploymentParameters.CroppedImage)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
MasterSuffix = "-master"
|
|
||||||
OwnerSuffix = "-owner"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *Service) TemporaryMasterContractAddress(hash string) string {
|
|
||||||
return hash + MasterSuffix
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) TemporaryOwnerContractAddress(hash string) string {
|
|
||||||
return hash + OwnerSuffix
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) HashFromTemporaryContractAddress(address string) string {
|
|
||||||
if strings.HasSuffix(address, OwnerSuffix) {
|
|
||||||
return strings.TrimSuffix(address, OwnerSuffix)
|
|
||||||
} else if strings.HasSuffix(address, MasterSuffix) {
|
|
||||||
return strings.TrimSuffix(address, MasterSuffix)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) GetMasterTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) ReTrackOwnerTokenDeploymentTransaction(ctx context.Context, chainID uint64, contractAddress string) error {
|
|
||||||
communityToken, err := s.Messenger.GetCommunityTokenByChainAndAddress(int(chainID), contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if communityToken == nil {
|
|
||||||
return fmt.Errorf("can't find token with address %v on chain %v", contractAddress, chainID)
|
|
||||||
}
|
|
||||||
if communityToken.DeployState != token.InProgress {
|
|
||||||
return fmt.Errorf("token with address %v on chain %v is not in progress", contractAddress, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
hashString := communityToken.TransactionHash
|
|
||||||
if hashString == "" && (communityToken.PrivilegesLevel == token.OwnerLevel || communityToken.PrivilegesLevel == token.MasterLevel) {
|
|
||||||
hashString = s.HashFromTemporaryContractAddress(communityToken.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hashString == "" {
|
|
||||||
return fmt.Errorf("can't find transaction hash for token with address %v on chain %v", contractAddress, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionType := transactions.DeployCommunityToken
|
|
||||||
if communityToken.PrivilegesLevel == token.OwnerLevel || communityToken.PrivilegesLevel == token.MasterLevel {
|
|
||||||
transactionType = transactions.DeployOwnerToken
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = s.pendingTracker.GetPendingEntry(wcommon.ChainID(chainID), common.HexToHash(hashString))
|
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
|
||||||
// start only if no pending transaction in database
|
|
||||||
err = s.pendingTracker.TrackPendingTransaction(
|
|
||||||
wcommon.ChainID(chainID),
|
|
||||||
common.HexToHash(hashString),
|
|
||||||
common.HexToAddress(communityToken.Deployer),
|
|
||||||
common.Address{},
|
|
||||||
transactionType,
|
|
||||||
transactions.Keep,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
logutils.ZapLogger().Debug("retracking pending transaction", zap.String("hashId", hashString))
|
|
||||||
} else {
|
|
||||||
logutils.ZapLogger().Debug("pending transaction already tracked", zap.String("hashId", hashString))
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) publishTokenActionToPrivilegedMembers(communityID string, chainID uint64, contractAddress string, actionType protobuf.CommunityTokenAction_ActionType) error {
|
|
||||||
decodedCommunityID, err := types.DecodeHex(communityID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.Messenger.PublishTokenActionToPrivilegedMembers(decodedCommunityID, chainID, contractAddress, actionType)
|
|
||||||
}
|
|
@ -1,176 +0,0 @@
|
|||||||
package communitytokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/assets"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/collectibles"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/mastertoken"
|
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/ownertoken"
|
|
||||||
"github.com/status-im/status-go/protocol/communities/token"
|
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TokenInstance interface {
|
|
||||||
RemoteBurn(*bind.TransactOpts, []*big.Int) (*types.Transaction, error)
|
|
||||||
Mint(*bind.TransactOpts, []string, *bigint.BigInt) (*types.Transaction, error)
|
|
||||||
SetMaxSupply(*bind.TransactOpts, *big.Int) (*types.Transaction, error)
|
|
||||||
PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Owner Token
|
|
||||||
type OwnerTokenInstance struct {
|
|
||||||
TokenInstance
|
|
||||||
instance *ownertoken.OwnerToken
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t OwnerTokenInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) {
|
|
||||||
return nil, fmt.Errorf("remote destruction for owner token not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t OwnerTokenInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) {
|
|
||||||
return nil, fmt.Errorf("minting for owner token not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t OwnerTokenInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) {
|
|
||||||
return nil, fmt.Errorf("setting max supply for owner token not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t OwnerTokenInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) {
|
|
||||||
ownerTokenABI, err := abi.JSON(strings.NewReader(ownertoken.OwnerTokenABI))
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return ownerTokenABI.Pack(methodName, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Master Token
|
|
||||||
type MasterTokenInstance struct {
|
|
||||||
TokenInstance
|
|
||||||
instance *mastertoken.MasterToken
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t MasterTokenInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) {
|
|
||||||
return t.instance.RemoteBurn(transactOpts, tokenIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t MasterTokenInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) {
|
|
||||||
usersAddresses := prepareMintCollectiblesData(walletAddresses, amount)
|
|
||||||
return t.instance.MintTo(transactOpts, usersAddresses)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t MasterTokenInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) {
|
|
||||||
return t.instance.SetMaxSupply(transactOpts, maxSupply)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t MasterTokenInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) {
|
|
||||||
masterTokenABI, err := abi.JSON(strings.NewReader(mastertoken.MasterTokenABI))
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return masterTokenABI.Pack(methodName, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collectible
|
|
||||||
type CollectibleInstance struct {
|
|
||||||
TokenInstance
|
|
||||||
instance *collectibles.Collectibles
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t CollectibleInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) {
|
|
||||||
return t.instance.RemoteBurn(transactOpts, tokenIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t CollectibleInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) {
|
|
||||||
usersAddresses := prepareMintCollectiblesData(walletAddresses, amount)
|
|
||||||
return t.instance.MintTo(transactOpts, usersAddresses)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t CollectibleInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) {
|
|
||||||
return t.instance.SetMaxSupply(transactOpts, maxSupply)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t CollectibleInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) {
|
|
||||||
collectiblesABI, err := abi.JSON(strings.NewReader(collectibles.CollectiblesABI))
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return collectiblesABI.Pack(methodName, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asset
|
|
||||||
type AssetInstance struct {
|
|
||||||
TokenInstance
|
|
||||||
instance *assets.Assets
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t AssetInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) {
|
|
||||||
return nil, fmt.Errorf("remote destruction for assets not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// The amount should be in smallest denomination of the asset (like wei) with decimal = 18, eg.
|
|
||||||
// if we want to mint 2.34 of the token, then amount should be 234{16 zeros}.
|
|
||||||
func (t AssetInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) {
|
|
||||||
usersAddresses, amountsList := prepareMintAssetsData(walletAddresses, amount)
|
|
||||||
return t.instance.MintTo(transactOpts, usersAddresses, amountsList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t AssetInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) {
|
|
||||||
return t.instance.SetMaxSupply(transactOpts, maxSupply)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t AssetInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) {
|
|
||||||
assetsABI, err := abi.JSON(strings.NewReader(assets.AssetsABI))
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return assetsABI.Pack(methodName, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// creator
|
|
||||||
|
|
||||||
func NewTokenInstance(s *Service, chainID uint64, contractAddress string) (TokenInstance, error) {
|
|
||||||
tokenType, err := s.db.GetTokenType(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
privLevel, err := s.db.GetTokenPrivilegesLevel(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case privLevel == token.OwnerLevel:
|
|
||||||
contractInst, err := s.NewOwnerTokenInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &OwnerTokenInstance{instance: contractInst}, nil
|
|
||||||
case privLevel == token.MasterLevel:
|
|
||||||
contractInst, err := s.NewMasterTokenInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &MasterTokenInstance{instance: contractInst}, nil
|
|
||||||
case tokenType == protobuf.CommunityTokenType_ERC721:
|
|
||||||
contractInst, err := s.manager.NewCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &CollectibleInstance{instance: contractInst}, nil
|
|
||||||
case tokenType == protobuf.CommunityTokenType_ERC20:
|
|
||||||
contractInst, err := s.manager.NewAssetsInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &AssetInstance{instance: contractInst}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unknown type of contract: chain=%v, address=%v", chainID, contractAddress)
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package communitytokens
|
|
||||||
|
|
||||||
const currentVersion = "1.0.0"
|
|
||||||
|
|
||||||
func (s *Service) currentVersion() string {
|
|
||||||
return currentVersion
|
|
||||||
}
|
|
@ -24,7 +24,7 @@ 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/rpc"
|
"github.com/status-im/status-go/rpc"
|
||||||
"github.com/status-im/status-go/services/communitytokens/communitytokensdatabase"
|
"github.com/status-im/status-go/services/communitytokensv2/communitytokensdatabase"
|
||||||
"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/requests"
|
"github.com/status-im/status-go/services/wallet/requests"
|
||||||
|
@ -52,7 +52,7 @@ 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/services/communitytokensv2"
|
||||||
"github.com/status-im/status-go/services/ext/mailservers"
|
"github.com/status-im/status-go/services/ext/mailservers"
|
||||||
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"
|
"github.com/status-im/status-go/services/wallet"
|
||||||
@ -127,7 +127,11 @@ func (s *Service) GetPeer(rawURL string) (*enode.Node, error) {
|
|||||||
return enode.ParseV4(rawURL)
|
return enode.ParseV4(rawURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) InitProtocol(nodeName string, identity *ecdsa.PrivateKey, appDb, walletDb *sql.DB, httpServer *server.MediaServer, multiAccountDb *multiaccounts.Database, acc *multiaccounts.Account, accountManager *account.GethManager, rpcClient *rpc.Client, walletService *wallet.Service, communityTokensService *communitytokens.Service, wakuService *wakuv2.Waku, logger *zap.Logger, accountsFeed *event.Feed) error {
|
func (s *Service) InitProtocol(nodeName string, identity *ecdsa.PrivateKey, appDb, walletDb *sql.DB,
|
||||||
|
httpServer *server.MediaServer, multiAccountDb *multiaccounts.Database, acc *multiaccounts.Account,
|
||||||
|
accountManager *account.GethManager, rpcClient *rpc.Client, walletService *wallet.Service,
|
||||||
|
communityTokensService *communitytokensv2.Service, wakuService *wakuv2.Waku, logger *zap.Logger,
|
||||||
|
accountsFeed *event.Feed) error {
|
||||||
var err error
|
var err error
|
||||||
if !s.config.ShhextConfig.PFSEnabled {
|
if !s.config.ShhextConfig.PFSEnabled {
|
||||||
return nil
|
return nil
|
||||||
@ -399,7 +403,7 @@ func buildMessengerOptions(
|
|||||||
envelopesMonitorConfig *transport.EnvelopesMonitorConfig,
|
envelopesMonitorConfig *transport.EnvelopesMonitorConfig,
|
||||||
accountsDB *accounts.Database,
|
accountsDB *accounts.Database,
|
||||||
walletService *wallet.Service,
|
walletService *wallet.Service,
|
||||||
communityTokensService *communitytokens.Service,
|
communityTokensService *communitytokensv2.Service,
|
||||||
wakuService *wakuv2.Waku,
|
wakuService *wakuv2.Waku,
|
||||||
logger *zap.Logger,
|
logger *zap.Logger,
|
||||||
messengerSignalsHandler protocol.MessengerSignalsHandler,
|
messengerSignalsHandler protocol.MessengerSignalsHandler,
|
||||||
|
@ -33,7 +33,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/communitytokensdatabase"
|
"github.com/status-im/status-go/services/communitytokensv2/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"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
"github.com/status-im/status-go/services/wallet/community"
|
"github.com/status-im/status-go/services/wallet/community"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user