feat(MasterToken): Add MasterToken.go
Small refactoring in Collectibles service in order to make API code more simple. Add TokenInstance interface with some common functions. Implementations of TokenInstance for TokenMaster, Collectibles and Assets contracts. Issue #11276
This commit is contained in:
parent
864b0686d2
commit
c4cd5775db
File diff suppressed because one or more lines are too long
|
@ -12,11 +12,11 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/status-im/status-go/account"
|
"github.com/status-im/status-go/account"
|
||||||
"github.com/status-im/status-go/contracts/community-tokens/assets"
|
"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/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/contracts/community-tokens/ownertoken"
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
|
@ -257,7 +257,15 @@ func (api *API) DeployOwnerTokenEstimate(ctx context.Context) (uint64, error) {
|
||||||
return ownerGasAmount + uint64(float32(ownerGasAmount)*0.1), nil
|
return ownerGasAmount + uint64(float32(ownerGasAmount)*0.1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) newCollectiblesInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
func (api *API) NewMasterTokenInstance(chainID uint64, contractAddress string) (*mastertoken.MasterToken, error) {
|
||||||
|
backend, err := api.RPCClient.EthClient(chainID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mastertoken.NewMasterToken(common.HexToAddress(contractAddress), backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) NewCollectiblesInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
||||||
backend, err := api.RPCClient.EthClient(chainID)
|
backend, err := api.RPCClient.EthClient(chainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -265,7 +273,7 @@ func (api *API) newCollectiblesInstance(chainID uint64, contractAddress string)
|
||||||
return collectibles.NewCollectibles(common.HexToAddress(contractAddress), backend)
|
return collectibles.NewCollectibles(common.HexToAddress(contractAddress), backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) newAssetsInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
func (api *API) NewAssetsInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
||||||
backend, err := api.RPCClient.EthClient(chainID)
|
backend, err := api.RPCClient.EthClient(chainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -284,7 +292,7 @@ func (api *API) multiplyWalletAddresses(amount *bigint.BigInt, contractAddresses
|
||||||
return totalAddresses
|
return totalAddresses
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) prepareMintCollectiblesData(walletAddresses []string, amount *bigint.BigInt) []common.Address {
|
func (api *API) PrepareMintCollectiblesData(walletAddresses []string, amount *bigint.BigInt) []common.Address {
|
||||||
totalAddresses := api.multiplyWalletAddresses(amount, walletAddresses)
|
totalAddresses := api.multiplyWalletAddresses(amount, walletAddresses)
|
||||||
var usersAddresses = []common.Address{}
|
var usersAddresses = []common.Address{}
|
||||||
for _, k := range totalAddresses {
|
for _, k := range totalAddresses {
|
||||||
|
@ -293,21 +301,34 @@ func (api *API) prepareMintCollectiblesData(walletAddresses []string, amount *bi
|
||||||
return usersAddresses
|
return usersAddresses
|
||||||
}
|
}
|
||||||
|
|
||||||
// Universal minting function for both assets and collectibles.
|
// Universal minting function for every type of token.
|
||||||
// Checks contract type and runs MintCollectibles or MintAssets function.
|
|
||||||
func (api *API) MintTokens(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, walletAddresses []string, amount *bigint.BigInt) (string, error) {
|
func (api *API) MintTokens(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, walletAddresses []string, amount *bigint.BigInt) (string, error) {
|
||||||
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
|
||||||
|
err := api.ValidateWalletsAndAmounts(walletAddresses, amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
switch tokenType {
|
|
||||||
case protobuf.CommunityTokenType_ERC721:
|
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.accountsManager, api.config.KeyStoreDir, txArgs.From, password))
|
||||||
return api.MintCollectibles(ctx, chainID, contractAddress, txArgs, password, walletAddresses, amount)
|
|
||||||
case protobuf.CommunityTokenType_ERC20:
|
contractInst, err := NewTokenInstance(api, chainID, contractAddress)
|
||||||
return api.MintAssets(ctx, chainID, contractAddress, txArgs, password, walletAddresses, amount)
|
if err != nil {
|
||||||
default:
|
return "", err
|
||||||
return "", fmt.Errorf("unknown token type: %v", tokenType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tx, err := contractInst.Mint(transactOpts, walletAddresses, amount)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
go api.rpcFiltersSrvc.TriggerTransactionSentToUpstreamEvent(&rpcfilters.PendingTxInfo{
|
||||||
|
Hash: tx.Hash(),
|
||||||
|
Type: string(transactions.AirdropCommunityToken),
|
||||||
|
From: common.Address(txArgs.From),
|
||||||
|
ChainID: chainID,
|
||||||
|
})
|
||||||
|
|
||||||
|
return tx.Hash().Hex(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) EstimateMintTokens(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
func (api *API) EstimateMintTokens(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
||||||
|
@ -315,6 +336,7 @@ func (api *API) EstimateMintTokens(ctx context.Context, chainID uint64, contract
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tokenType {
|
switch tokenType {
|
||||||
case protobuf.CommunityTokenType_ERC721:
|
case protobuf.CommunityTokenType_ERC721:
|
||||||
return api.EstimateMintCollectibles(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
return api.EstimateMintCollectibles(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
||||||
|
@ -325,47 +347,16 @@ func (api *API) EstimateMintTokens(ctx context.Context, chainID uint64, contract
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the amounty of collectible tokens and distribute them to all walletAddresses.
|
|
||||||
func (api *API) MintCollectibles(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, walletAddresses []string, amount *bigint.BigInt) (string, error) {
|
|
||||||
err := api.validateWalletsAndAmounts(walletAddresses, amount)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
usersAddresses := api.prepareMintCollectiblesData(walletAddresses, amount)
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.accountsManager, api.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
tx, err := contractInst.MintTo(transactOpts, usersAddresses)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
go api.rpcFiltersSrvc.TriggerTransactionSentToUpstreamEvent(&rpcfilters.PendingTxInfo{
|
|
||||||
Hash: tx.Hash(),
|
|
||||||
Type: string(transactions.AirdropCommunityToken),
|
|
||||||
From: common.Address(txArgs.From),
|
|
||||||
ChainID: chainID,
|
|
||||||
})
|
|
||||||
|
|
||||||
return tx.Hash().Hex(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) EstimateMintCollectibles(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
func (api *API) EstimateMintCollectibles(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
||||||
err := api.validateWalletsAndAmounts(walletAddresses, amount)
|
err := api.ValidateWalletsAndAmounts(walletAddresses, amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
usersAddresses := api.prepareMintCollectiblesData(walletAddresses, amount)
|
usersAddresses := api.PrepareMintCollectiblesData(walletAddresses, amount)
|
||||||
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "mintTo", usersAddresses)
|
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "mintTo", usersAddresses)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) prepareMintAssetsData(walletAddresses []string, amount *bigint.BigInt) ([]common.Address, []*big.Int) {
|
func (api *API) PrepareMintAssetsData(walletAddresses []string, amount *bigint.BigInt) ([]common.Address, []*big.Int) {
|
||||||
var usersAddresses = []common.Address{}
|
var usersAddresses = []common.Address{}
|
||||||
var amountsList = []*big.Int{}
|
var amountsList = []*big.Int{}
|
||||||
for _, k := range walletAddresses {
|
for _, k := range walletAddresses {
|
||||||
|
@ -375,53 +366,20 @@ func (api *API) prepareMintAssetsData(walletAddresses []string, amount *bigint.B
|
||||||
return usersAddresses, amountsList
|
return usersAddresses, amountsList
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the amount of assets tokens and distribute them to all walletAddresses.
|
|
||||||
// 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 (api *API) MintAssets(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, walletAddresses []string, amount *bigint.BigInt) (string, error) {
|
|
||||||
err := api.validateWalletsAndAmounts(walletAddresses, amount)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
contractInst, err := api.newAssetsInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
usersAddresses, amountsList := api.prepareMintAssetsData(walletAddresses, amount)
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.accountsManager, api.config.KeyStoreDir, txArgs.From, password))
|
|
||||||
|
|
||||||
tx, err := contractInst.MintTo(transactOpts, usersAddresses, amountsList)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
go api.rpcFiltersSrvc.TriggerTransactionSentToUpstreamEvent(&rpcfilters.PendingTxInfo{
|
|
||||||
Hash: tx.Hash(),
|
|
||||||
Type: string(transactions.AirdropCommunityToken),
|
|
||||||
From: common.Address(txArgs.From),
|
|
||||||
ChainID: chainID,
|
|
||||||
})
|
|
||||||
|
|
||||||
return tx.Hash().Hex(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Estimate MintAssets cost.
|
// Estimate MintAssets cost.
|
||||||
func (api *API) EstimateMintAssets(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
func (api *API) EstimateMintAssets(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, walletAddresses []string, amount *bigint.BigInt) (uint64, error) {
|
||||||
err := api.validateWalletsAndAmounts(walletAddresses, amount)
|
err := api.ValidateWalletsAndAmounts(walletAddresses, amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
usersAddresses, amountsList := api.prepareMintAssetsData(walletAddresses, amount)
|
usersAddresses, amountsList := api.PrepareMintAssetsData(walletAddresses, amount)
|
||||||
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "mintTo", usersAddresses, amountsList)
|
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "mintTo", usersAddresses, amountsList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only ERC721 function
|
// This is only ERC721 function
|
||||||
func (api *API) RemoteDestructedAmount(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
func (api *API) RemoteDestructedAmount(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
contractInst, err := api.NewCollectiblesInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -451,11 +409,6 @@ func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.accountsManager, api.config.KeyStoreDir, txArgs.From, password))
|
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.accountsManager, api.config.KeyStoreDir, txArgs.From, password))
|
||||||
|
|
||||||
var tempTokenIds []*big.Int
|
var tempTokenIds []*big.Int
|
||||||
|
@ -463,6 +416,11 @@ func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress
|
||||||
tempTokenIds = append(tempTokenIds, v.Int)
|
tempTokenIds = append(tempTokenIds, v.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contractInst, err := NewTokenInstance(api, chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
tx, err := contractInst.RemoteBurn(transactOpts, tempTokenIds)
|
tx, err := contractInst.RemoteBurn(transactOpts, tempTokenIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -494,7 +452,7 @@ func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contract
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetCollectiblesContractInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
func (api *API) GetCollectiblesContractInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
contractInst, err := api.NewCollectiblesInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -502,7 +460,7 @@ func (api *API) GetCollectiblesContractInstance(chainID uint64, contractAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetAssetContractInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
func (api *API) GetAssetContractInstance(chainID uint64, contractAddress string) (*assets.Assets, error) {
|
||||||
contractInst, err := api.newAssetsInstance(chainID, contractAddress)
|
contractInst, err := api.NewAssetsInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -527,7 +485,7 @@ func (api *API) RemainingSupply(ctx context.Context, chainID uint64, contractAdd
|
||||||
// RemainingSupply = MaxSupply - MintedCount
|
// RemainingSupply = MaxSupply - MintedCount
|
||||||
func (api *API) remainingCollectiblesSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
func (api *API) remainingCollectiblesSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
contractInst, err := api.NewCollectiblesInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -547,7 +505,7 @@ func (api *API) remainingCollectiblesSupply(ctx context.Context, chainID uint64,
|
||||||
// RemainingSupply = MaxSupply - TotalSupply
|
// RemainingSupply = MaxSupply - TotalSupply
|
||||||
func (api *API) remainingAssetsSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
func (api *API) remainingAssetsSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
contractInst, err := api.newAssetsInstance(chainID, contractAddress)
|
contractInst, err := api.NewAssetsInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -566,7 +524,7 @@ func (api *API) remainingAssetsSupply(ctx context.Context, chainID uint64, contr
|
||||||
|
|
||||||
func (api *API) maxSupplyCollectibles(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
func (api *API) maxSupplyCollectibles(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
contractInst, err := api.NewCollectiblesInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -575,7 +533,7 @@ func (api *API) maxSupplyCollectibles(ctx context.Context, chainID uint64, contr
|
||||||
|
|
||||||
func (api *API) maxSupplyAssets(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
func (api *API) maxSupplyAssets(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
contractInst, err := api.newAssetsInstance(chainID, contractAddress)
|
contractInst, err := api.NewAssetsInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -608,38 +566,6 @@ func (api *API) prepareNewMaxSupply(ctx context.Context, chainID uint64, contrac
|
||||||
return newMaxSupply, nil
|
return newMaxSupply, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) setMaxSupplyCollectibles(transactOpts *bind.TransactOpts, chainID uint64, contractAddress string, newMaxSupply *big.Int) (*types.Transaction, error) {
|
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return contractInst.SetMaxSupply(transactOpts, newMaxSupply)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) setMaxSupplyAssets(transactOpts *bind.TransactOpts, chainID uint64, contractAddress string, newMaxSupply *big.Int) (*types.Transaction, error) {
|
|
||||||
contractInst, err := api.newAssetsInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return contractInst.SetMaxSupply(transactOpts, newMaxSupply)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) setMaxSupply(transactOpts *bind.TransactOpts, chainID uint64, contractAddress string, newMaxSupply *big.Int) (*types.Transaction, error) {
|
|
||||||
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tokenType {
|
|
||||||
case protobuf.CommunityTokenType_ERC721:
|
|
||||||
return api.setMaxSupplyCollectibles(transactOpts, chainID, contractAddress, newMaxSupply)
|
|
||||||
case protobuf.CommunityTokenType_ERC20:
|
|
||||||
return api.setMaxSupplyAssets(transactOpts, chainID, contractAddress, newMaxSupply)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown token type: %v", tokenType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) Burn(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, burnAmount *bigint.BigInt) (string, error) {
|
func (api *API) Burn(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, burnAmount *bigint.BigInt) (string, error) {
|
||||||
err := api.validateBurnAmount(ctx, burnAmount, chainID, contractAddress)
|
err := api.validateBurnAmount(ctx, burnAmount, chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -653,7 +579,12 @@ func (api *API) Burn(ctx context.Context, chainID uint64, contractAddress string
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, err := api.setMaxSupply(transactOpts, chainID, contractAddress, newMaxSupply)
|
contractInst, err := NewTokenInstance(api, chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := contractInst.SetMaxSupply(transactOpts, newMaxSupply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -682,7 +613,7 @@ func (api *API) EstimateBurn(ctx context.Context, chainID uint64, contractAddres
|
||||||
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "setMaxSupply", newMaxSupply)
|
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "setMaxSupply", newMaxSupply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) validateWalletsAndAmounts(walletAddresses []string, amount *bigint.BigInt) error {
|
func (api *API) ValidateWalletsAndAmounts(walletAddresses []string, amount *bigint.BigInt) error {
|
||||||
if len(walletAddresses) == 0 {
|
if len(walletAddresses) == 0 {
|
||||||
return errors.New("wallet addresses list is empty")
|
return errors.New("wallet addresses list is empty")
|
||||||
}
|
}
|
||||||
|
@ -713,22 +644,6 @@ func (api *API) validateBurnAmount(ctx context.Context, burnAmount *bigint.BigIn
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) packCollectibleMethod(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...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) packAssetsMethod(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...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) estimateMethod(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, methodName string, args ...interface{}) (uint64, error) {
|
func (api *API) estimateMethod(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, methodName string, args ...interface{}) (uint64, error) {
|
||||||
ethClient, err := api.RPCClient.EthClient(chainID)
|
ethClient, err := api.RPCClient.EthClient(chainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -736,20 +651,13 @@ func (api *API) estimateMethod(ctx context.Context, chainID uint64, contractAddr
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
contractInst, err := NewTokenInstance(api, chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
var data []byte
|
|
||||||
|
|
||||||
switch tokenType {
|
data, err := contractInst.PackMethod(ctx, methodName, args...)
|
||||||
case protobuf.CommunityTokenType_ERC721:
|
|
||||||
data, err = api.packCollectibleMethod(ctx, methodName, args...)
|
|
||||||
case protobuf.CommunityTokenType_ERC20:
|
|
||||||
data, err = api.packAssetsMethod(ctx, methodName, args...)
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("unknown token type: %v", tokenType)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,3 +30,18 @@ func (db *Database) GetTokenType(chainID uint64, contractAddress string) (protob
|
||||||
}
|
}
|
||||||
return result, fmt.Errorf("can't find token: chainId %v, contractAddress %v", chainID, contractAddress)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -109,3 +109,16 @@ func (s *DatabaseSuite) TestGetTokenType() {
|
||||||
_, err = s.db.GetTokenType(10, "0x777")
|
_, err = s.db.GetTokenType(10, "0x777")
|
||||||
s.Require().Error(err)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
package collectibles
|
||||||
|
|
||||||
|
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/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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Master Token
|
||||||
|
type MasterTokenInstance struct {
|
||||||
|
TokenInstance
|
||||||
|
instance *mastertoken.MasterToken
|
||||||
|
api *API
|
||||||
|
}
|
||||||
|
|
||||||
|
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 := t.api.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
|
||||||
|
api *API
|
||||||
|
}
|
||||||
|
|
||||||
|
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 := t.api.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
|
||||||
|
api *API
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t AssetInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) {
|
||||||
|
return nil, fmt.Errorf("remote burn 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 := t.api.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(api *API, chainID uint64, contractAddress string) (TokenInstance, error) {
|
||||||
|
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
privLevel, err := api.db.GetTokenPrivilegesLevel(chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case privLevel == token.MasterLevel:
|
||||||
|
contractInst, err := api.NewMasterTokenInstance(chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &MasterTokenInstance{instance: contractInst}, nil
|
||||||
|
case tokenType == protobuf.CommunityTokenType_ERC721:
|
||||||
|
contractInst, err := api.NewCollectiblesInstance(chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &CollectibleInstance{instance: contractInst}, nil
|
||||||
|
case tokenType == protobuf.CommunityTokenType_ERC20:
|
||||||
|
contractInst, err := api.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)
|
||||||
|
}
|
Loading…
Reference in New Issue