2023-08-25 15:36:39 +00:00
|
|
|
package communitytokens
|
2023-08-14 08:27:46 +00:00
|
|
|
|
|
|
|
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) {
|
2023-08-22 17:48:42 +00:00
|
|
|
tokenType, err := api.s.db.GetTokenType(chainID, contractAddress)
|
2023-08-14 08:27:46 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-08-22 17:48:42 +00:00
|
|
|
privLevel, err := api.s.db.GetTokenPrivilegesLevel(chainID, contractAddress)
|
2023-08-14 08:27:46 +00:00
|
|
|
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)
|
|
|
|
}
|