github.com/status-im/status-go@v1.1.0/services/communitytokens/token_instances.go (about) 1 package communitytokens 2 3 import ( 4 "context" 5 "fmt" 6 "math/big" 7 "strings" 8 9 "github.com/ethereum/go-ethereum/accounts/abi" 10 "github.com/ethereum/go-ethereum/accounts/abi/bind" 11 "github.com/ethereum/go-ethereum/core/types" 12 "github.com/status-im/status-go/contracts/community-tokens/assets" 13 "github.com/status-im/status-go/contracts/community-tokens/collectibles" 14 "github.com/status-im/status-go/contracts/community-tokens/mastertoken" 15 "github.com/status-im/status-go/contracts/community-tokens/ownertoken" 16 "github.com/status-im/status-go/protocol/communities/token" 17 "github.com/status-im/status-go/protocol/protobuf" 18 "github.com/status-im/status-go/services/wallet/bigint" 19 ) 20 21 type TokenInstance interface { 22 RemoteBurn(*bind.TransactOpts, []*big.Int) (*types.Transaction, error) 23 Mint(*bind.TransactOpts, []string, *bigint.BigInt) (*types.Transaction, error) 24 SetMaxSupply(*bind.TransactOpts, *big.Int) (*types.Transaction, error) 25 PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) 26 } 27 28 // Owner Token 29 type OwnerTokenInstance struct { 30 TokenInstance 31 instance *ownertoken.OwnerToken 32 } 33 34 func (t OwnerTokenInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) { 35 return nil, fmt.Errorf("remote destruction for owner token not implemented") 36 } 37 38 func (t OwnerTokenInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) { 39 return nil, fmt.Errorf("minting for owner token not implemented") 40 } 41 42 func (t OwnerTokenInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) { 43 return nil, fmt.Errorf("setting max supply for owner token not implemented") 44 } 45 46 func (t OwnerTokenInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) { 47 ownerTokenABI, err := abi.JSON(strings.NewReader(ownertoken.OwnerTokenABI)) 48 if err != nil { 49 return []byte{}, err 50 } 51 return ownerTokenABI.Pack(methodName, args...) 52 } 53 54 // Master Token 55 type MasterTokenInstance struct { 56 TokenInstance 57 instance *mastertoken.MasterToken 58 } 59 60 func (t MasterTokenInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) { 61 return t.instance.RemoteBurn(transactOpts, tokenIds) 62 } 63 64 func (t MasterTokenInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) { 65 usersAddresses := prepareMintCollectiblesData(walletAddresses, amount) 66 return t.instance.MintTo(transactOpts, usersAddresses) 67 } 68 69 func (t MasterTokenInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) { 70 return t.instance.SetMaxSupply(transactOpts, maxSupply) 71 } 72 73 func (t MasterTokenInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) { 74 masterTokenABI, err := abi.JSON(strings.NewReader(mastertoken.MasterTokenABI)) 75 if err != nil { 76 return []byte{}, err 77 } 78 return masterTokenABI.Pack(methodName, args...) 79 } 80 81 // Collectible 82 type CollectibleInstance struct { 83 TokenInstance 84 instance *collectibles.Collectibles 85 } 86 87 func (t CollectibleInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) { 88 return t.instance.RemoteBurn(transactOpts, tokenIds) 89 } 90 91 func (t CollectibleInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) { 92 usersAddresses := prepareMintCollectiblesData(walletAddresses, amount) 93 return t.instance.MintTo(transactOpts, usersAddresses) 94 } 95 96 func (t CollectibleInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) { 97 return t.instance.SetMaxSupply(transactOpts, maxSupply) 98 } 99 100 func (t CollectibleInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) { 101 collectiblesABI, err := abi.JSON(strings.NewReader(collectibles.CollectiblesABI)) 102 if err != nil { 103 return []byte{}, err 104 } 105 return collectiblesABI.Pack(methodName, args...) 106 } 107 108 // Asset 109 type AssetInstance struct { 110 TokenInstance 111 instance *assets.Assets 112 } 113 114 func (t AssetInstance) RemoteBurn(transactOpts *bind.TransactOpts, tokenIds []*big.Int) (*types.Transaction, error) { 115 return nil, fmt.Errorf("remote destruction for assets not implemented") 116 } 117 118 // The amount should be in smallest denomination of the asset (like wei) with decimal = 18, eg. 119 // if we want to mint 2.34 of the token, then amount should be 234{16 zeros}. 120 func (t AssetInstance) Mint(transactOpts *bind.TransactOpts, walletAddresses []string, amount *bigint.BigInt) (*types.Transaction, error) { 121 usersAddresses, amountsList := prepareMintAssetsData(walletAddresses, amount) 122 return t.instance.MintTo(transactOpts, usersAddresses, amountsList) 123 } 124 125 func (t AssetInstance) SetMaxSupply(transactOpts *bind.TransactOpts, maxSupply *big.Int) (*types.Transaction, error) { 126 return t.instance.SetMaxSupply(transactOpts, maxSupply) 127 } 128 129 func (t AssetInstance) PackMethod(ctx context.Context, methodName string, args ...interface{}) ([]byte, error) { 130 assetsABI, err := abi.JSON(strings.NewReader(assets.AssetsABI)) 131 if err != nil { 132 return []byte{}, err 133 } 134 return assetsABI.Pack(methodName, args...) 135 } 136 137 // creator 138 139 func NewTokenInstance(s *Service, chainID uint64, contractAddress string) (TokenInstance, error) { 140 tokenType, err := s.db.GetTokenType(chainID, contractAddress) 141 if err != nil { 142 return nil, err 143 } 144 privLevel, err := s.db.GetTokenPrivilegesLevel(chainID, contractAddress) 145 if err != nil { 146 return nil, err 147 } 148 switch { 149 case privLevel == token.OwnerLevel: 150 contractInst, err := s.NewOwnerTokenInstance(chainID, contractAddress) 151 if err != nil { 152 return nil, err 153 } 154 return &OwnerTokenInstance{instance: contractInst}, nil 155 case privLevel == token.MasterLevel: 156 contractInst, err := s.NewMasterTokenInstance(chainID, contractAddress) 157 if err != nil { 158 return nil, err 159 } 160 return &MasterTokenInstance{instance: contractInst}, nil 161 case tokenType == protobuf.CommunityTokenType_ERC721: 162 contractInst, err := s.manager.NewCollectiblesInstance(chainID, contractAddress) 163 if err != nil { 164 return nil, err 165 } 166 return &CollectibleInstance{instance: contractInst}, nil 167 case tokenType == protobuf.CommunityTokenType_ERC20: 168 contractInst, err := s.manager.NewAssetsInstance(chainID, contractAddress) 169 if err != nil { 170 return nil, err 171 } 172 return &AssetInstance{instance: contractInst}, nil 173 } 174 175 return nil, fmt.Errorf("unknown type of contract: chain=%v, address=%v", chainID, contractAddress) 176 }