feat(OwnerToken): Owner token and master token deployment
Adding new smart contracts and generated go files. Deploy token owner function and master token address getter. Adding deployer and privilegesLevel columns to community_tokens table. Passing addressFrom to API calls. Issue #11250
This commit is contained in:
parent
b49b9fe3c5
commit
9d0acc2265
File diff suppressed because one or more lines are too long
|
@ -3,14 +3,14 @@ pragma solidity ^0.8.17;
|
||||||
|
|
||||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
|
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
|
||||||
import "@openzeppelin/contracts/utils/Context.sol";
|
import "@openzeppelin/contracts/utils/Context.sol";
|
||||||
import "@openzeppelin/contracts/utils/Counters.sol";
|
import "@openzeppelin/contracts/utils/Counters.sol";
|
||||||
|
|
||||||
contract CollectibleV1 is
|
abstract contract BaseToken is
|
||||||
Context,
|
Context,
|
||||||
ERC721Enumerable,
|
ERC721Enumerable
|
||||||
Ownable
|
|
||||||
{
|
{
|
||||||
using Counters for Counters.Counter;
|
using Counters for Counters.Counter;
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@ contract CollectibleV1 is
|
||||||
*/
|
*/
|
||||||
uint256 public maxSupply;
|
uint256 public maxSupply;
|
||||||
|
|
||||||
|
address public ownerToken;
|
||||||
|
address public masterToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to true, the contract owner can burn any token.
|
* If set to true, the contract owner can burn any token.
|
||||||
*/
|
*/
|
||||||
|
@ -41,19 +44,35 @@ contract CollectibleV1 is
|
||||||
uint256 _maxSupply,
|
uint256 _maxSupply,
|
||||||
bool _remoteBurnable,
|
bool _remoteBurnable,
|
||||||
bool _transferable,
|
bool _transferable,
|
||||||
string memory _baseTokenURI
|
string memory _baseTokenURI,
|
||||||
|
address _ownerToken,
|
||||||
|
address _masterToken
|
||||||
) ERC721(_name, _symbol) {
|
) ERC721(_name, _symbol) {
|
||||||
maxSupply = _maxSupply;
|
maxSupply = _maxSupply;
|
||||||
remoteBurnable = _remoteBurnable;
|
remoteBurnable = _remoteBurnable;
|
||||||
transferable = _transferable;
|
transferable = _transferable;
|
||||||
baseTokenURI = _baseTokenURI;
|
baseTokenURI = _baseTokenURI;
|
||||||
|
ownerToken = _ownerToken;
|
||||||
|
masterToken = _masterToken;
|
||||||
|
|
||||||
|
require(ownerToken != address(0x0) || masterToken != address(0x0), "owner or master tokens required");
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier onlyOwner() {
|
||||||
|
require(
|
||||||
|
(ownerToken == address(0) || IERC721(ownerToken).balanceOf(msg.sender) > 0) ||
|
||||||
|
(masterToken == address(0) || IERC721(masterToken).balanceOf(msg.sender) > 0),
|
||||||
|
"Not authorized"
|
||||||
|
);
|
||||||
|
|
||||||
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
|
||||||
// External functions
|
// External functions
|
||||||
|
|
||||||
function setMaxSupply(uint256 newMaxSupply) external onlyOwner {
|
function setMaxSupply(uint256 newMaxSupply) virtual external onlyOwner {
|
||||||
require(newMaxSupply >= totalSupply(), "MAX_SUPPLY_LOWER_THAN_TOTAL_SUPPLY");
|
require(newMaxSupply >= totalSupply(), "MAX_SUPPLY_LOWER_THAN_TOTAL_SUPPLY");
|
||||||
maxSupply = newMaxSupply;
|
maxSupply = newMaxSupply;
|
||||||
}
|
}
|
||||||
|
@ -64,15 +83,9 @@ contract CollectibleV1 is
|
||||||
* URI autogenerated based on the base URI passed at construction.
|
* URI autogenerated based on the base URI passed at construction.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function mintTo(address[] memory addresses) external onlyOwner {
|
function mintTo(address[] memory addresses) public onlyOwner {
|
||||||
// We cannot just use totalSupply() to create the new tokenId because tokens
|
|
||||||
// can be burned so we use a separate counter.
|
|
||||||
require(_tokenIdTracker.current() + addresses.length <= maxSupply, "MAX_SUPPLY_REACHED");
|
require(_tokenIdTracker.current() + addresses.length <= maxSupply, "MAX_SUPPLY_REACHED");
|
||||||
|
_mintTo(addresses);
|
||||||
for (uint256 i = 0; i < addresses.length; i++) {
|
|
||||||
_safeMint(addresses[i], _tokenIdTracker.current(), "");
|
|
||||||
_tokenIdTracker.increment();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
@ -116,6 +129,15 @@ contract CollectibleV1 is
|
||||||
return baseTokenURI;
|
return baseTokenURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _mintTo(address[] memory addresses) internal {
|
||||||
|
// We cannot just use totalSupply() to create the new tokenId because tokens
|
||||||
|
// can be burned so we use a separate counter.
|
||||||
|
for (uint256 i = 0; i < addresses.length; i++) {
|
||||||
|
_safeMint(addresses[i], _tokenIdTracker.current(), "");
|
||||||
|
_tokenIdTracker.increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice
|
* @notice
|
||||||
* @dev
|
* @dev
|
|
@ -0,0 +1,26 @@
|
||||||
|
// SPDX-License-Identifier: Mozilla Public License 2.0
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
import "./BaseToken.sol";
|
||||||
|
|
||||||
|
contract CollectibleV1 is BaseToken {
|
||||||
|
constructor(
|
||||||
|
string memory _name,
|
||||||
|
string memory _symbol,
|
||||||
|
uint256 _maxSupply,
|
||||||
|
bool _remoteBurnable,
|
||||||
|
bool _transferable,
|
||||||
|
string memory _baseTokenURI,
|
||||||
|
address _ownerToken,
|
||||||
|
address _masterToken
|
||||||
|
) BaseToken(
|
||||||
|
_name,
|
||||||
|
_symbol,
|
||||||
|
_maxSupply,
|
||||||
|
_remoteBurnable,
|
||||||
|
_transferable,
|
||||||
|
_baseTokenURI,
|
||||||
|
_ownerToken,
|
||||||
|
_masterToken) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,12 +15,16 @@ contract CommunityERC20 is
|
||||||
*/
|
*/
|
||||||
uint256 public maxSupply;
|
uint256 public maxSupply;
|
||||||
|
|
||||||
|
uint8 private customDecimals;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
string memory _name,
|
string memory _name,
|
||||||
string memory _symbol,
|
string memory _symbol,
|
||||||
|
uint8 _decimals,
|
||||||
uint256 _maxSupply
|
uint256 _maxSupply
|
||||||
) ERC20(_name, _symbol) {
|
) ERC20(_name, _symbol) {
|
||||||
maxSupply = _maxSupply;
|
maxSupply = _maxSupply;
|
||||||
|
customDecimals = _decimals;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
@ -48,6 +52,9 @@ contract CommunityERC20 is
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
function decimals() public view virtual override returns (uint8) {
|
||||||
|
return customDecimals;
|
||||||
|
}
|
||||||
|
|
||||||
// Internal functions
|
// Internal functions
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: Mozilla Public License 2.0
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
import "./BaseToken.sol";
|
||||||
|
|
||||||
|
contract MasterToken is BaseToken {
|
||||||
|
constructor(
|
||||||
|
string memory _name,
|
||||||
|
string memory _symbol,
|
||||||
|
string memory _baseTokenURI,
|
||||||
|
address _ownerToken
|
||||||
|
) BaseToken(
|
||||||
|
_name,
|
||||||
|
_symbol,
|
||||||
|
type(uint256).max,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
_baseTokenURI,
|
||||||
|
_ownerToken,
|
||||||
|
address(0x0)) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// SPDX-License-Identifier: Mozilla Public License 2.0
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
import "./BaseToken.sol";
|
||||||
|
import "./MasterToken.sol";
|
||||||
|
|
||||||
|
contract OwnerToken is BaseToken {
|
||||||
|
event MasterTokenCreated(address masterToken);
|
||||||
|
|
||||||
|
bytes public signerPublicKey;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
string memory _name,
|
||||||
|
string memory _symbol,
|
||||||
|
string memory _baseTokenURI,
|
||||||
|
string memory _masterName,
|
||||||
|
string memory _masterSymbol,
|
||||||
|
string memory _masterBaseTokenURI,
|
||||||
|
bytes memory _signerPublicKey
|
||||||
|
) BaseToken(
|
||||||
|
_name,
|
||||||
|
_symbol,
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
_baseTokenURI,
|
||||||
|
address(this),
|
||||||
|
address(this))
|
||||||
|
{
|
||||||
|
signerPublicKey = _signerPublicKey;
|
||||||
|
MasterToken masterToken = new MasterToken(_masterName, _masterSymbol, _masterBaseTokenURI, address(this));
|
||||||
|
emit MasterTokenCreated(address(masterToken));
|
||||||
|
address[] memory addresses = new address[](1);
|
||||||
|
addresses[0] = msg.sender;
|
||||||
|
_mintTo(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMaxSupply(uint256 _newMaxSupply) override external onlyOwner {
|
||||||
|
revert("max supply locked");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSignerPublicKey(bytes memory _newSignerPublicKey) external onlyOwner {
|
||||||
|
signerPublicKey = _newSignerPublicKey;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
|
@ -9,6 +9,7 @@ import (
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/nfnt/resize"
|
"github.com/nfnt/resize"
|
||||||
)
|
)
|
||||||
|
@ -127,3 +128,7 @@ func GetPayloadFromURI(uri string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
return base64.StdEncoding.DecodeString(res[2])
|
return base64.StdEncoding.DecodeString(res[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsPayloadDataURI(uri string) bool {
|
||||||
|
return strings.HasPrefix(uri, "data:image")
|
||||||
|
}
|
||||||
|
|
|
@ -4224,7 +4224,8 @@ func (m *Manager) SaveCommunityToken(token *community_token.CommunityToken, crop
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
token.Base64Image = base64img
|
token.Base64Image = base64img
|
||||||
} else {
|
} else if !images.IsPayloadDataURI(token.Base64Image) {
|
||||||
|
// if image is already base64 do not convert (owner and master tokens have already base64 image)
|
||||||
token.Base64Image = m.ImageToBase64(token.Base64Image)
|
token.Base64Image = m.ImageToBase64(token.Base64Image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4267,6 +4268,10 @@ func (m *Manager) UpdateCommunityTokenState(chainID int, contractAddress string,
|
||||||
return m.persistence.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
return m.persistence.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) UpdateCommunityTokenAddress(chainID int, oldContractAddress string, newContractAddress string) error {
|
||||||
|
return m.persistence.UpdateCommunityTokenAddress(chainID, oldContractAddress, newContractAddress)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
func (m *Manager) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
||||||
return m.persistence.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
return m.persistence.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
||||||
}
|
}
|
||||||
|
@ -4486,7 +4491,7 @@ func (m *Manager) HandleCommunityTokensMetadata(communityID string, communityTok
|
||||||
|
|
||||||
switch tokenMetadata.TokenType {
|
switch tokenMetadata.TokenType {
|
||||||
case protobuf.CommunityTokenType_ERC721:
|
case protobuf.CommunityTokenType_ERC721:
|
||||||
contract, err := m.collectiblesService.API().GetContractInstance(chainID, address)
|
contract, err := m.collectiblesService.API().GetCollectiblesContractInstance(chainID, address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1179,8 +1179,8 @@ func (p *Persistence) GetCommunityChatIDs(communityID types.HexBytes) ([]string,
|
||||||
|
|
||||||
func (p *Persistence) GetAllCommunityTokens() ([]*token.CommunityToken, error) {
|
func (p *Persistence) GetAllCommunityTokens() ([]*token.CommunityToken, error) {
|
||||||
rows, err := p.db.Query(`SELECT community_id, address, type, name, symbol, description, supply_str,
|
rows, err := p.db.Query(`SELECT community_id, address, type, name, symbol, description, supply_str,
|
||||||
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals
|
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals,
|
||||||
FROM community_tokens`)
|
deployer, privileges_level FROM community_tokens`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1191,7 +1191,8 @@ func (p *Persistence) GetAllCommunityTokens() ([]*token.CommunityToken, error) {
|
||||||
|
|
||||||
func (p *Persistence) GetCommunityTokens(communityID string) ([]*token.CommunityToken, error) {
|
func (p *Persistence) GetCommunityTokens(communityID string) ([]*token.CommunityToken, error) {
|
||||||
rows, err := p.db.Query(`SELECT community_id, address, type, name, symbol, description, supply_str,
|
rows, err := p.db.Query(`SELECT community_id, address, type, name, symbol, description, supply_str,
|
||||||
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals
|
infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals,
|
||||||
|
deployer, privileges_level
|
||||||
FROM community_tokens WHERE community_id = ?`, communityID)
|
FROM community_tokens WHERE community_id = ?`, communityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1204,9 +1205,12 @@ func (p *Persistence) GetCommunityTokens(communityID string) ([]*token.Community
|
||||||
func (p *Persistence) GetCommunityToken(communityID string, chainID int, address string) (*token.CommunityToken, error) {
|
func (p *Persistence) GetCommunityToken(communityID string, chainID int, address string) (*token.CommunityToken, error) {
|
||||||
token := token.CommunityToken{}
|
token := token.CommunityToken{}
|
||||||
var supplyStr string
|
var supplyStr string
|
||||||
err := p.db.QueryRow(`SELECT community_id, address, type, name, symbol, description, supply_str, infinite_supply, transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals FROM community_tokens WHERE community_id = ? AND chain_id = ? AND address = ?`, communityID, chainID, address).Scan(&token.CommunityID, &token.Address, &token.TokenType, &token.Name,
|
err := p.db.QueryRow(`SELECT community_id, address, type, name, symbol, description, supply_str, infinite_supply,
|
||||||
|
transferable, remote_self_destruct, chain_id, deploy_state, image_base64, decimals, deployer, privileges_level
|
||||||
|
FROM community_tokens WHERE community_id = ? AND chain_id = ? AND address = ?`, communityID, chainID, address).Scan(&token.CommunityID, &token.Address, &token.TokenType, &token.Name,
|
||||||
&token.Symbol, &token.Description, &supplyStr, &token.InfiniteSupply, &token.Transferable,
|
&token.Symbol, &token.Description, &supplyStr, &token.InfiniteSupply, &token.Transferable,
|
||||||
&token.RemoteSelfDestruct, &token.ChainID, &token.DeployState, &token.Base64Image, &token.Decimals)
|
&token.RemoteSelfDestruct, &token.ChainID, &token.DeployState, &token.Base64Image, &token.Decimals,
|
||||||
|
&token.Deployer, &token.PrivilegesLevel)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@ -1229,7 +1233,8 @@ func (p *Persistence) getCommunityTokensInternal(rows *sql.Rows) ([]*token.Commu
|
||||||
var supplyStr string
|
var supplyStr string
|
||||||
err := rows.Scan(&token.CommunityID, &token.Address, &token.TokenType, &token.Name,
|
err := rows.Scan(&token.CommunityID, &token.Address, &token.TokenType, &token.Name,
|
||||||
&token.Symbol, &token.Description, &supplyStr, &token.InfiniteSupply, &token.Transferable,
|
&token.Symbol, &token.Description, &supplyStr, &token.InfiniteSupply, &token.Transferable,
|
||||||
&token.RemoteSelfDestruct, &token.ChainID, &token.DeployState, &token.Base64Image, &token.Decimals)
|
&token.RemoteSelfDestruct, &token.ChainID, &token.DeployState, &token.Base64Image, &token.Decimals,
|
||||||
|
&token.Deployer, &token.PrivilegesLevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1257,10 +1262,10 @@ func (p *Persistence) HasCommunityToken(communityID string, address string, chai
|
||||||
|
|
||||||
func (p *Persistence) AddCommunityToken(token *token.CommunityToken) error {
|
func (p *Persistence) AddCommunityToken(token *token.CommunityToken) error {
|
||||||
_, err := p.db.Exec(`INSERT INTO community_tokens (community_id, address, type, name, symbol, description, supply_str,
|
_, err := p.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)
|
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,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, token.CommunityID, token.Address, token.TokenType, token.Name,
|
||||||
token.Symbol, token.Description, token.Supply.String(), token.InfiniteSupply, token.Transferable, token.RemoteSelfDestruct,
|
token.Symbol, token.Description, token.Supply.String(), token.InfiniteSupply, token.Transferable, token.RemoteSelfDestruct,
|
||||||
token.ChainID, token.DeployState, token.Base64Image, token.Decimals)
|
token.ChainID, token.DeployState, token.Base64Image, token.Decimals, token.Deployer, token.PrivilegesLevel)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1269,6 +1274,11 @@ func (p *Persistence) UpdateCommunityTokenState(chainID int, contractAddress str
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Persistence) UpdateCommunityTokenAddress(chainID int, oldContractAddress string, newContractAddress string) error {
|
||||||
|
_, err := p.db.Exec(`UPDATE community_tokens SET address = ? WHERE address = ? AND chain_id = ?`, newContractAddress, oldContractAddress, chainID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Persistence) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
func (p *Persistence) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
||||||
_, err := p.db.Exec(`UPDATE community_tokens SET supply_str = ? WHERE address = ? AND chain_id = ?`, supply.String(), contractAddress, chainID)
|
_, err := p.db.Exec(`UPDATE community_tokens SET supply_str = ? WHERE address = ? AND chain_id = ?`, supply.String(), contractAddress, chainID)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -422,6 +422,8 @@ func (s *PersistenceSuite) TestGetCommunityTokens() {
|
||||||
ChainID: 1,
|
ChainID: 1,
|
||||||
DeployState: token.InProgress,
|
DeployState: token.InProgress,
|
||||||
Base64Image: "ABCD",
|
Base64Image: "ABCD",
|
||||||
|
Deployer: "0xDep1",
|
||||||
|
PrivilegesLevel: token.OwnerLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenERC20 := token.CommunityToken{
|
tokenERC20 := token.CommunityToken{
|
||||||
|
@ -439,6 +441,8 @@ func (s *PersistenceSuite) TestGetCommunityTokens() {
|
||||||
DeployState: token.Failed,
|
DeployState: token.Failed,
|
||||||
Base64Image: "QWERTY",
|
Base64Image: "QWERTY",
|
||||||
Decimals: 21,
|
Decimals: 21,
|
||||||
|
Deployer: "0xDep2",
|
||||||
|
PrivilegesLevel: token.CommunityLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.db.AddCommunityToken(&tokenERC721)
|
err = s.db.AddCommunityToken(&tokenERC721)
|
||||||
|
@ -462,6 +466,13 @@ func (s *PersistenceSuite) TestGetCommunityTokens() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Len(tokens, 1)
|
s.Require().Len(tokens, 1)
|
||||||
s.Require().Equal(tokenERC20, *tokens[0])
|
s.Require().Equal(tokenERC20, *tokens[0])
|
||||||
|
|
||||||
|
err = s.db.UpdateCommunityTokenAddress(1, "0x123", "0x123-newAddr")
|
||||||
|
s.Require().NoError(err)
|
||||||
|
tokens, err = s.db.GetCommunityTokens("123")
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(tokens, 1)
|
||||||
|
s.Require().Equal("0x123-newAddr", tokens[0].Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PersistenceSuite) TestSaveCheckChannelPermissionResponse() {
|
func (s *PersistenceSuite) TestSaveCheckChannelPermissionResponse() {
|
||||||
|
|
|
@ -13,6 +13,14 @@ const (
|
||||||
Deployed
|
Deployed
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PrivilegesLevel uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
OwnerLevel PrivilegesLevel = iota
|
||||||
|
MasterLevel
|
||||||
|
CommunityLevel
|
||||||
|
)
|
||||||
|
|
||||||
type CommunityToken struct {
|
type CommunityToken struct {
|
||||||
TokenType protobuf.CommunityTokenType `json:"tokenType"`
|
TokenType protobuf.CommunityTokenType `json:"tokenType"`
|
||||||
CommunityID string `json:"communityId"`
|
CommunityID string `json:"communityId"`
|
||||||
|
@ -28,4 +36,6 @@ type CommunityToken struct {
|
||||||
DeployState DeployState `json:"deployState"`
|
DeployState DeployState `json:"deployState"`
|
||||||
Base64Image string `json:"image"`
|
Base64Image string `json:"image"`
|
||||||
Decimals int `json:"decimals"`
|
Decimals int `json:"decimals"`
|
||||||
|
Deployer string `json:"deployer"`
|
||||||
|
PrivilegesLevel PrivilegesLevel `json:"privilegesLevel"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -4160,6 +4160,10 @@ func (m *Messenger) UpdateCommunityTokenState(chainID int, contractAddress strin
|
||||||
return m.communitiesManager.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
return m.communitiesManager.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Messenger) UpdateCommunityTokenAddress(chainID int, oldContractAddress string, newContractAddress string) error {
|
||||||
|
return m.communitiesManager.UpdateCommunityTokenAddress(chainID, oldContractAddress, newContractAddress)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Messenger) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
func (m *Messenger) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
||||||
return m.communitiesManager.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
return m.communitiesManager.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE community_tokens ADD COLUMN deployer TEXT NOT NULL DEFAULT "";
|
||||||
|
ALTER TABLE community_tokens ADD COLUMN privileges_level INT NOT NULL DEFAULT 2;
|
|
@ -15,8 +15,10 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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/assets"
|
"github.com/status-im/status-go/contracts/community-tokens/assets"
|
||||||
"github.com/status-im/status-go/contracts/collectibles"
|
"github.com/status-im/status-go/contracts/community-tokens/collectibles"
|
||||||
|
"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/params"
|
"github.com/status-im/status-go/params"
|
||||||
"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"
|
||||||
|
@ -59,6 +61,8 @@ type DeploymentParameters struct {
|
||||||
Transferable bool `json:"transferable"`
|
Transferable bool `json:"transferable"`
|
||||||
RemoteSelfDestruct bool `json:"remoteSelfDestruct"`
|
RemoteSelfDestruct bool `json:"remoteSelfDestruct"`
|
||||||
TokenURI string `json:"tokenUri"`
|
TokenURI string `json:"tokenUri"`
|
||||||
|
OwnerTokenAddress string `json:"ownerTokenAddress"`
|
||||||
|
MasterTokenAddress string `json:"masterTokenAddress"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeploymentParameters) GetSupply() *big.Int {
|
func (d *DeploymentParameters) GetSupply() *big.Int {
|
||||||
|
@ -115,7 +119,8 @@ func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deployme
|
||||||
address, tx, _, err := collectibles.DeployCollectibles(transactOpts, ethClient, deploymentParameters.Name,
|
address, tx, _, err := collectibles.DeployCollectibles(transactOpts, ethClient, deploymentParameters.Name,
|
||||||
deploymentParameters.Symbol, deploymentParameters.GetSupply(),
|
deploymentParameters.Symbol, deploymentParameters.GetSupply(),
|
||||||
deploymentParameters.RemoteSelfDestruct, deploymentParameters.Transferable,
|
deploymentParameters.RemoteSelfDestruct, deploymentParameters.Transferable,
|
||||||
deploymentParameters.TokenURI)
|
deploymentParameters.TokenURI, common.HexToAddress(deploymentParameters.OwnerTokenAddress),
|
||||||
|
common.HexToAddress(deploymentParameters.MasterTokenAddress))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
return DeploymentDetails{}, err
|
return DeploymentDetails{}, err
|
||||||
|
@ -131,6 +136,77 @@ func (api *API) DeployCollectibles(ctx context.Context, chainID uint64, deployme
|
||||||
return DeploymentDetails{address.Hex(), tx.Hash().Hex()}, nil
|
return DeploymentDetails{address.Hex(), tx.Hash().Hex()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) DeployOwnerToken(ctx context.Context, chainID uint64, ownerTokenParameters DeploymentParameters, masterTokenParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||||
|
err := ownerTokenParameters.Validate(false)
|
||||||
|
if err != nil {
|
||||||
|
return DeploymentDetails{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = masterTokenParameters.Validate(false)
|
||||||
|
if err != nil {
|
||||||
|
return DeploymentDetails{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.accountsManager, api.config.KeyStoreDir, txArgs.From, password))
|
||||||
|
|
||||||
|
ethClient, err := api.RPCClient.EthClient(chainID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return DeploymentDetails{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
signerPubKey := []byte{}
|
||||||
|
|
||||||
|
address, tx, _, err := ownertoken.DeployOwnerToken(transactOpts, ethClient, ownerTokenParameters.Name,
|
||||||
|
ownerTokenParameters.Symbol, ownerTokenParameters.TokenURI,
|
||||||
|
masterTokenParameters.Name, masterTokenParameters.Symbol,
|
||||||
|
masterTokenParameters.TokenURI, signerPubKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return DeploymentDetails{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go api.rpcFiltersSrvc.TriggerTransactionSentToUpstreamEvent(&rpcfilters.PendingTxInfo{
|
||||||
|
Hash: tx.Hash(),
|
||||||
|
Type: string(transactions.DeployOwnerToken),
|
||||||
|
From: common.Address(txArgs.From),
|
||||||
|
ChainID: chainID,
|
||||||
|
})
|
||||||
|
|
||||||
|
return DeploymentDetails{address.Hex(), tx.Hash().Hex()}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) GetMasterTokenContractAddressFromHash(ctx context.Context, chainID uint64, txHash string) (string, error) {
|
||||||
|
ethClient, err := api.RPCClient.EthClient(chainID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
receipt, err := ethClient.TransactionReceipt(ctx, common.HexToHash(txHash))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
logMasterTokenCreatedSig := []byte("MasterTokenCreated(address)")
|
||||||
|
logMasterTokenCreatedSigHash := crypto.Keccak256Hash(logMasterTokenCreatedSig)
|
||||||
|
|
||||||
|
for _, vLog := range receipt.Logs {
|
||||||
|
if vLog.Topics[0].Hex() == logMasterTokenCreatedSigHash.Hex() {
|
||||||
|
ownerTokenABI, err := abi.JSON(strings.NewReader(ownertoken.OwnerTokenABI))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
event := new(ownertoken.OwnerTokenMasterTokenCreated)
|
||||||
|
err = ownerTokenABI.UnpackIntoInterface(event, "MasterTokenCreated", vLog.Data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return event.MasterToken.Hex(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("can't find master token address in transaction: %v", txHash)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentParameters DeploymentParameters, txArgs transactions.SendTxArgs, password string) (DeploymentDetails, error) {
|
||||||
|
|
||||||
err := deploymentParameters.Validate(true)
|
err := deploymentParameters.Validate(true)
|
||||||
|
@ -165,7 +241,7 @@ func (api *API) DeployAssets(ctx context.Context, chainID uint64, deploymentPara
|
||||||
|
|
||||||
// Returns gas units + 10%
|
// Returns gas units + 10%
|
||||||
func (api *API) DeployCollectiblesEstimate(ctx context.Context) (uint64, error) {
|
func (api *API) DeployCollectiblesEstimate(ctx context.Context) (uint64, error) {
|
||||||
gasAmount := uint64(1960645)
|
gasAmount := uint64(2091605)
|
||||||
return gasAmount + uint64(float32(gasAmount)*0.1), nil
|
return gasAmount + uint64(float32(gasAmount)*0.1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +251,12 @@ func (api *API) DeployAssetsEstimate(ctx context.Context) (uint64, error) {
|
||||||
return gasAmount + uint64(float32(gasAmount)*0.1), nil
|
return gasAmount + uint64(float32(gasAmount)*0.1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns gas units + 10%
|
||||||
|
func (api *API) DeployOwnerTokenEstimate(ctx context.Context) (uint64, error) {
|
||||||
|
ownerGasAmount := uint64(4389457)
|
||||||
|
return ownerGasAmount + uint64(float32(ownerGasAmount)*0.1), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) newCollectiblesInstance(chainID uint64, contractAddress string) (*collectibles.Collectibles, error) {
|
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 {
|
||||||
|
@ -228,16 +310,16 @@ func (api *API) MintTokens(ctx context.Context, chainID uint64, contractAddress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) EstimateMintTokens(ctx context.Context, chainID uint64, contractAddress 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) {
|
||||||
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
||||||
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, walletAddresses, amount)
|
return api.EstimateMintCollectibles(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
||||||
case protobuf.CommunityTokenType_ERC20:
|
case protobuf.CommunityTokenType_ERC20:
|
||||||
return api.EstimateMintAssets(ctx, chainID, contractAddress, walletAddresses, amount)
|
return api.EstimateMintAssets(ctx, chainID, contractAddress, fromAddress, walletAddresses, amount)
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("unknown token type: %v", tokenType)
|
return 0, fmt.Errorf("unknown token type: %v", tokenType)
|
||||||
}
|
}
|
||||||
|
@ -274,13 +356,13 @@ func (api *API) MintCollectibles(ctx context.Context, chainID uint64, contractAd
|
||||||
return tx.Hash().Hex(), nil
|
return tx.Hash().Hex(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) EstimateMintCollectibles(ctx context.Context, chainID uint64, contractAddress 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, "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) {
|
||||||
|
@ -327,13 +409,13 @@ func (api *API) MintAssets(ctx context.Context, chainID uint64, contractAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estimate MintAssets cost.
|
// Estimate MintAssets cost.
|
||||||
func (api *API) EstimateMintAssets(ctx context.Context, chainID uint64, contractAddress 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, "mintTo", usersAddresses, amountsList)
|
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "mintTo", usersAddresses, amountsList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only ERC721 function
|
// This is only ERC721 function
|
||||||
|
@ -397,7 +479,7 @@ func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only ERC721 function
|
// This is only ERC721 function
|
||||||
func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contractAddress string, tokenIds []*bigint.BigInt) (uint64, error) {
|
func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, tokenIds []*bigint.BigInt) (uint64, error) {
|
||||||
err := api.validateTokens(tokenIds)
|
err := api.validateTokens(tokenIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -408,10 +490,10 @@ func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contract
|
||||||
tempTokenIds = append(tempTokenIds, v.Int)
|
tempTokenIds = append(tempTokenIds, v.Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.estimateMethod(ctx, chainID, contractAddress, "remoteBurn", tempTokenIds)
|
return api.estimateMethod(ctx, chainID, contractAddress, fromAddress, "remoteBurn", tempTokenIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetContractInstance(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
|
||||||
|
@ -427,36 +509,6 @@ func (api *API) GetAssetContractInstance(chainID uint64, contractAddress string)
|
||||||
return contractInst, nil
|
return contractInst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) ContractOwner(ctx context.Context, chainID uint64, contractAddress string) (string, error) {
|
|
||||||
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
|
||||||
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if tokenType == protobuf.CommunityTokenType_ERC721 {
|
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
owner, err := contractInst.Owner(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return owner.String(), nil
|
|
||||||
} else if tokenType == protobuf.CommunityTokenType_ERC20 {
|
|
||||||
contractInst, err := api.newAssetsInstance(chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
owner, err := contractInst.Owner(callOpts)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return owner.String(), nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("unknown token type: %v", tokenType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) RemainingSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
func (api *API) RemainingSupply(ctx context.Context, chainID uint64, contractAddress string) (*bigint.BigInt, error) {
|
||||||
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
tokenType, err := api.db.GetTokenType(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -616,7 +668,7 @@ func (api *API) Burn(ctx context.Context, chainID uint64, contractAddress string
|
||||||
return tx.Hash().Hex(), nil
|
return tx.Hash().Hex(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) EstimateBurn(ctx context.Context, chainID uint64, contractAddress string, burnAmount *bigint.BigInt) (uint64, error) {
|
func (api *API) EstimateBurn(ctx context.Context, chainID uint64, contractAddress string, fromAddress string, burnAmount *bigint.BigInt) (uint64, error) {
|
||||||
err := api.validateBurnAmount(ctx, burnAmount, chainID, contractAddress)
|
err := api.validateBurnAmount(ctx, burnAmount, chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -627,7 +679,7 @@ func (api *API) EstimateBurn(ctx context.Context, chainID uint64, contractAddres
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.estimateMethod(ctx, chainID, contractAddress, "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 {
|
||||||
|
@ -677,7 +729,7 @@ func (api *API) packAssetsMethod(ctx context.Context, methodName string, args ..
|
||||||
return assetsABI.Pack(methodName, args...)
|
return assetsABI.Pack(methodName, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) estimateMethod(ctx context.Context, chainID uint64, contractAddress 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 {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
|
@ -702,13 +754,8 @@ func (api *API) estimateMethod(ctx context.Context, chainID uint64, contractAddr
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ownerAddr, err := api.ContractOwner(ctx, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
toAddr := common.HexToAddress(contractAddress)
|
toAddr := common.HexToAddress(contractAddress)
|
||||||
fromAddr := common.HexToAddress(ownerAddr)
|
fromAddr := common.HexToAddress(fromAddress)
|
||||||
|
|
||||||
callMsg := ethereum.CallMsg{
|
callMsg := ethereum.CallMsg{
|
||||||
From: fromAddr,
|
From: fromAddr,
|
||||||
|
|
|
@ -17,37 +17,37 @@ func TestDeploymentParameters(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "emptyName",
|
name: "emptyName",
|
||||||
parameters: DeploymentParameters{"", "SYMBOL", &bigint.BigInt{Int: big.NewInt(int64(123))}, false, false, false, ""},
|
parameters: DeploymentParameters{"", "SYMBOL", &bigint.BigInt{Int: big.NewInt(int64(123))}, false, false, false, "", "", ""},
|
||||||
isError: true,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "emptySymbol",
|
name: "emptySymbol",
|
||||||
parameters: DeploymentParameters{"NAME", "", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, ""},
|
parameters: DeploymentParameters{"NAME", "", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, "", "", ""},
|
||||||
isError: true,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negativeSupply",
|
name: "negativeSupply",
|
||||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, false, false, false, ""},
|
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, false, false, false, "", "", ""},
|
||||||
isError: true,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zeroSupply",
|
name: "zeroSupply",
|
||||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(0)}, false, false, false, ""},
|
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(0)}, false, false, false, "", "", ""},
|
||||||
isError: false,
|
isError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negativeSupplyAndInfinite",
|
name: "negativeSupplyAndInfinite",
|
||||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, true, false, false, ""},
|
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(-123)}, true, false, false, "", "", ""},
|
||||||
isError: false,
|
isError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "supplyGreaterThanMax",
|
name: "supplyGreaterThanMax",
|
||||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply + 1)}, false, false, false, ""},
|
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply + 1)}, false, false, false, "", "", ""},
|
||||||
isError: true,
|
isError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "supplyIsMax",
|
name: "supplyIsMax",
|
||||||
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply)}, false, false, false, ""},
|
parameters: DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(maxSupply)}, false, false, false, "", "", ""},
|
||||||
isError: false,
|
isError: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,10 @@ func TestDeploymentParameters(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
notInfiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, ""}
|
notInfiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, false, false, false, "", "", ""}
|
||||||
requiredSupply := big.NewInt(123)
|
requiredSupply := big.NewInt(123)
|
||||||
require.Equal(t, notInfiniteSupplyParams.GetSupply(), requiredSupply)
|
require.Equal(t, notInfiniteSupplyParams.GetSupply(), requiredSupply)
|
||||||
infiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, true, false, false, ""}
|
infiniteSupplyParams := DeploymentParameters{"NAME", "SYM", &bigint.BigInt{Int: big.NewInt(123)}, true, false, false, "", "", ""}
|
||||||
requiredSupply = infiniteSupplyParams.GetInfiniteSupply()
|
requiredSupply = infiniteSupplyParams.GetInfiniteSupply()
|
||||||
require.Equal(t, infiniteSupplyParams.GetSupply(), requiredSupply)
|
require.Equal(t, infiniteSupplyParams.GetSupply(), requiredSupply)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ type DatabaseSuite struct {
|
||||||
|
|
||||||
func (s *DatabaseSuite) addCommunityToken(db *sql.DB, token *token.CommunityToken) error {
|
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,
|
_, 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)
|
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,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, token.CommunityID, token.Address, token.TokenType, token.Name,
|
||||||
token.Symbol, token.Description, token.Supply.String(), token.InfiniteSupply, token.Transferable, token.RemoteSelfDestruct,
|
token.Symbol, token.Description, token.Supply.String(), token.InfiniteSupply, token.Transferable, token.RemoteSelfDestruct,
|
||||||
token.ChainID, token.DeployState, token.Base64Image, token.Decimals)
|
token.ChainID, token.DeployState, token.Base64Image, token.Decimals, token.Deployer, token.PrivilegesLevel)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ func (s *DatabaseSuite) setupDatabase(db *sql.DB) error {
|
||||||
ChainID: 1,
|
ChainID: 1,
|
||||||
DeployState: token.InProgress,
|
DeployState: token.InProgress,
|
||||||
Base64Image: "ABCD",
|
Base64Image: "ABCD",
|
||||||
|
Deployer: "0xDEP1",
|
||||||
|
PrivilegesLevel: token.OwnerLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
token20 := &token.CommunityToken{
|
token20 := &token.CommunityToken{
|
||||||
|
@ -66,6 +68,8 @@ func (s *DatabaseSuite) setupDatabase(db *sql.DB) error {
|
||||||
DeployState: token.Failed,
|
DeployState: token.Failed,
|
||||||
Base64Image: "QWERTY",
|
Base64Image: "QWERTY",
|
||||||
Decimals: 21,
|
Decimals: 21,
|
||||||
|
Deployer: "0xDEP2",
|
||||||
|
PrivilegesLevel: token.CommunityLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.addCommunityToken(db, token721)
|
err := s.addCommunityToken(db, token721)
|
||||||
|
|
|
@ -1353,6 +1353,10 @@ func (api *PublicAPI) UpdateCommunityTokenState(chainID int, contractAddress str
|
||||||
return api.service.messenger.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
return api.service.messenger.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *PublicAPI) UpdateCommunityTokenAddress(chainID int, oldContractAddress string, newContractAddress string) error {
|
||||||
|
return api.service.messenger.UpdateCommunityTokenAddress(chainID, oldContractAddress, newContractAddress)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *PublicAPI) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
func (api *PublicAPI) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply *bigint.BigInt) error {
|
||||||
return api.service.messenger.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
return api.service.messenger.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"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/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/status-im/status-go/contracts/collectibles"
|
"github.com/status-im/status-go/contracts/community-tokens/collectibles"
|
||||||
"github.com/status-im/status-go/rpc"
|
"github.com/status-im/status-go/rpc"
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
walletCommon "github.com/status-im/status-go/services/wallet/common"
|
walletCommon "github.com/status-im/status-go/services/wallet/common"
|
||||||
|
|
|
@ -103,6 +103,7 @@ const (
|
||||||
AirdropCommunityToken PendingTrxType = "AirdropCommunityToken"
|
AirdropCommunityToken PendingTrxType = "AirdropCommunityToken"
|
||||||
RemoteDestructCollectible PendingTrxType = "RemoteDestructCollectible"
|
RemoteDestructCollectible PendingTrxType = "RemoteDestructCollectible"
|
||||||
BurnCommunityToken PendingTrxType = "BurnCommunityToken"
|
BurnCommunityToken PendingTrxType = "BurnCommunityToken"
|
||||||
|
DeployOwnerToken PendingTrxType = "DeployOwnerToken"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PendingTransaction struct {
|
type PendingTransaction struct {
|
||||||
|
|
Loading…
Reference in New Issue