feat(BurnCollectibles): Add burn collectibles functionality
Change smart contract with new API. Update gas amount for deployment. Add Burn() and EstimateBurn() functions. Add RemainingSupply() functions. Issue #10816
This commit is contained in:
parent
8015cc3e3b
commit
ccde92377d
|
@ -53,6 +53,11 @@ contract CollectibleV1 is
|
||||||
|
|
||||||
// External functions
|
// External functions
|
||||||
|
|
||||||
|
function setMaxSupply(uint256 newMaxSupply) external onlyOwner {
|
||||||
|
require(newMaxSupply >= totalSupply(), "MAX_SUPPLY_LOWER_THAN_TOTAL_SUPPLY");
|
||||||
|
maxSupply = newMaxSupply;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Creates a new token for each address in `addresses`. Its token ID will be automatically
|
* @dev Creates a new token for each address in `addresses`. Its token ID will be automatically
|
||||||
* assigned (and available on the emitted {IERC721-Transfer} event), and the token
|
* assigned (and available on the emitted {IERC721-Transfer} event), and the token
|
||||||
|
@ -62,7 +67,7 @@ contract CollectibleV1 is
|
||||||
function mintTo(address[] memory addresses) external onlyOwner {
|
function mintTo(address[] memory addresses) external onlyOwner {
|
||||||
// We cannot just use totalSupply() to create the new tokenId because tokens
|
// We cannot just use totalSupply() to create the new tokenId because tokens
|
||||||
// can be burned so we use a separate counter.
|
// 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");
|
||||||
|
|
||||||
for (uint256 i = 0; i < addresses.length; i++) {
|
for (uint256 i = 0; i < addresses.length; i++) {
|
||||||
_safeMint(addresses[i], _tokenIdTracker.current(), "");
|
_safeMint(addresses[i], _tokenIdTracker.current(), "");
|
||||||
|
@ -72,6 +77,10 @@ contract CollectibleV1 is
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
|
function mintedCount() public view returns (uint256) {
|
||||||
|
return _tokenIdTracker.current();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice remoteBurn allows the owner to burn a token
|
* @notice remoteBurn allows the owner to burn a token
|
||||||
* @param tokenIds The list of token IDs to be burned
|
* @param tokenIds The list of token IDs to be burned
|
||||||
|
@ -117,6 +126,9 @@ contract CollectibleV1 is
|
||||||
uint256 firstTokenId,
|
uint256 firstTokenId,
|
||||||
uint256 batchSize
|
uint256 batchSize
|
||||||
) internal virtual override(ERC721Enumerable) {
|
) internal virtual override(ERC721Enumerable) {
|
||||||
|
if (from != address(0) && to != address(0) && !transferable) {
|
||||||
|
revert("not transferable");
|
||||||
|
}
|
||||||
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
|
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3845,8 +3845,12 @@ func (m *Manager) AddCommunityToken(token *CommunityToken) (*CommunityToken, err
|
||||||
return token, m.persistence.AddCommunityToken(token)
|
return token, m.persistence.AddCommunityToken(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) UpdateCommunityTokenState(contractAddress string, deployState DeployState) error {
|
func (m *Manager) UpdateCommunityTokenState(chainID int, contractAddress string, deployState DeployState) error {
|
||||||
return m.persistence.UpdateCommunityTokenState(contractAddress, deployState)
|
return m.persistence.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply int) error {
|
||||||
|
return m.persistence.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) SetCommunityActiveMembersCount(communityID string, activeMembersCount uint64) error {
|
func (m *Manager) SetCommunityActiveMembersCount(communityID string, activeMembersCount uint64) error {
|
||||||
|
|
|
@ -988,7 +988,12 @@ func (p *Persistence) AddCommunityToken(token *CommunityToken) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Persistence) UpdateCommunityTokenState(contractAddress string, deployState DeployState) error {
|
func (p *Persistence) UpdateCommunityTokenState(chainID int, contractAddress string, deployState DeployState) error {
|
||||||
_, err := p.db.Exec(`UPDATE community_tokens SET deploy_state = ? WHERE address = ?`, deployState, contractAddress)
|
_, err := p.db.Exec(`UPDATE community_tokens SET deploy_state = ? WHERE address = ? AND chain_id = ?`, deployState, contractAddress, chainID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Persistence) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply int) error {
|
||||||
|
_, err := p.db.Exec(`UPDATE community_tokens SET supply = ? WHERE address = ? AND chain_id = ?`, supply, contractAddress, chainID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,7 +417,7 @@ func (s *PersistenceSuite) TestGetCommunityTokens() {
|
||||||
s.Require().Len(tokens, 1)
|
s.Require().Len(tokens, 1)
|
||||||
s.Require().Equal(token, *tokens[0])
|
s.Require().Equal(token, *tokens[0])
|
||||||
|
|
||||||
err = s.db.UpdateCommunityTokenState("0x123", Deployed)
|
err = s.db.UpdateCommunityTokenState(1, "0x123", Deployed)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
tokens, err = s.db.GetCommunityTokens("123")
|
tokens, err = s.db.GetCommunityTokens("123")
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
|
@ -3731,8 +3731,12 @@ func (m *Messenger) AddCommunityToken(token *communities.CommunityToken) (*commu
|
||||||
return m.communitiesManager.AddCommunityToken(token)
|
return m.communitiesManager.AddCommunityToken(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) UpdateCommunityTokenState(contractAddress string, deployState communities.DeployState) error {
|
func (m *Messenger) UpdateCommunityTokenState(chainID int, contractAddress string, deployState communities.DeployState) error {
|
||||||
return m.communitiesManager.UpdateCommunityTokenState(contractAddress, deployState)
|
return m.communitiesManager.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Messenger) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply int) error {
|
||||||
|
return m.communitiesManager.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCommunityEncryption takes a community and encrypts / decrypts the community
|
// UpdateCommunityEncryption takes a community and encrypts / decrypts the community
|
||||||
|
|
|
@ -111,7 +111,8 @@ func (api *API) Deploy(ctx context.Context, chainID uint64, deploymentParameters
|
||||||
|
|
||||||
// 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) {
|
||||||
return 3702411, nil
|
gasAmount := uint64(1960645)
|
||||||
|
return gasAmount + uint64(float32(gasAmount)*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) {
|
||||||
|
@ -166,17 +167,6 @@ func (api *API) EstimateMintTo(ctx context.Context, chainID uint64, contractAddr
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ethClient, err := api.RPCClient.EthClient(chainID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err.Error())
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
collectiblesABI, err := abi.JSON(strings.NewReader(collectibles.CollectiblesABI))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
totalAddresses := api.multiplyWalletAddresses(amount, walletAddresses)
|
totalAddresses := api.multiplyWalletAddresses(amount, walletAddresses)
|
||||||
|
|
||||||
var usersAddresses = []common.Address{}
|
var usersAddresses = []common.Address{}
|
||||||
|
@ -184,35 +174,13 @@ func (api *API) EstimateMintTo(ctx context.Context, chainID uint64, contractAddr
|
||||||
usersAddresses = append(usersAddresses, common.HexToAddress(k))
|
usersAddresses = append(usersAddresses, common.HexToAddress(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := collectiblesABI.Pack("mintTo", usersAddresses)
|
return api.estimateMethod(ctx, chainID, contractAddress, "mintTo", usersAddresses)
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ownerAddr, err := api.ContractOwner(ctx, chainID, contractAddress)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
toAddr := common.HexToAddress(contractAddress)
|
|
||||||
fromAddr := common.HexToAddress(ownerAddr)
|
|
||||||
|
|
||||||
callMsg := ethereum.CallMsg{
|
|
||||||
From: fromAddr,
|
|
||||||
To: &toAddr,
|
|
||||||
Value: big.NewInt(0),
|
|
||||||
Data: data,
|
|
||||||
}
|
|
||||||
|
|
||||||
estimate, err := ethClient.EstimateGas(ctx, callMsg)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return estimate + uint64(float32(estimate)*0.1), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, tokenIds []*bigint.BigInt) (string, error) {
|
func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress string, txArgs transactions.SendTxArgs, password string, tokenIds []*bigint.BigInt) (string, error) {
|
||||||
if len(tokenIds) == 0 {
|
err := api.validateTokens(tokenIds)
|
||||||
return "", errors.New("tokenIds list is empty")
|
if err != nil {
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
||||||
|
@ -235,6 +203,20 @@ func (api *API) RemoteBurn(ctx context.Context, chainID uint64, contractAddress
|
||||||
return tx.Hash().Hex(), nil
|
return tx.Hash().Hex(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contractAddress string, tokenIds []*bigint.BigInt) (uint64, error) {
|
||||||
|
err := api.validateTokens(tokenIds)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempTokenIds []*big.Int
|
||||||
|
for _, v := range tokenIds {
|
||||||
|
tempTokenIds = append(tempTokenIds, v.Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
return api.estimateMethod(ctx, chainID, contractAddress, "remoteBurn", tempTokenIds)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) ContractOwner(ctx context.Context, chainID uint64, contractAddress string) (string, error) {
|
func (api *API) ContractOwner(ctx context.Context, chainID uint64, contractAddress string) (string, 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)
|
||||||
|
@ -248,14 +230,90 @@ func (api *API) ContractOwner(ctx context.Context, chainID uint64, contractAddre
|
||||||
return owner.String(), nil
|
return owner.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) AddTokenOwners(ctx context.Context, chainID uint64, contractAddress string, walletAddresses []string, amount int) error {
|
func (api *API) MintedCount(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||||
err := api.validateWalletsAndAmounts(walletAddresses, amount)
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
|
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
|
}
|
||||||
|
mintedCount, err := contractInst.MintedCount(callOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mintedCount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemainingSupply = MaxSupply - MintedCount
|
||||||
|
func (api *API) RemainingSupply(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||||
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
|
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
maxSupply, err := contractInst.MaxSupply(callOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mintedCount, err := contractInst.MintedCount(callOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var res = new(big.Int)
|
||||||
|
res.Sub(maxSupply, mintedCount)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) maxSupply(ctx context.Context, chainID uint64, contractAddress string) (*big.Int, error) {
|
||||||
|
callOpts := &bind.CallOpts{Context: ctx, Pending: false}
|
||||||
|
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return contractInst.MaxSupply(callOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
totalAddresses := api.multiplyWalletAddresses(amount, walletAddresses)
|
contractInst, err := api.newCollectiblesInstance(chainID, contractAddress)
|
||||||
return api.db.AddTokenOwners(chainID, contractAddress, totalAddresses)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
transactOpts := txArgs.ToTransactOpts(utils.GetSigner(chainID, api.accountsManager, api.config.KeyStoreDir, txArgs.From, password))
|
||||||
|
|
||||||
|
maxSupply, err := api.maxSupply(ctx, chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var newMaxSupply = new(big.Int)
|
||||||
|
newMaxSupply.Sub(maxSupply, burnAmount.Int)
|
||||||
|
|
||||||
|
tx, err := contractInst.SetMaxSupply(transactOpts, newMaxSupply)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Hash().Hex(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) EstimateBurn(ctx context.Context, chainID uint64, contractAddress string, burnAmount *bigint.BigInt) (uint64, error) {
|
||||||
|
err := api.validateBurnAmount(ctx, burnAmount, chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
maxSupply, err := api.maxSupply(ctx, chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var newMaxSupply = new(big.Int)
|
||||||
|
newMaxSupply.Sub(maxSupply, burnAmount.Int)
|
||||||
|
|
||||||
|
return api.estimateMethod(ctx, chainID, contractAddress, "setMaxSupply", newMaxSupply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) validateWalletsAndAmounts(walletAddresses []string, amount int) error {
|
func (api *API) validateWalletsAndAmounts(walletAddresses []string, amount int) error {
|
||||||
|
@ -268,11 +326,28 @@ func (api *API) validateWalletsAndAmounts(walletAddresses []string, amount int)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contractAddress string, tokenIds []*bigint.BigInt) (uint64, error) {
|
func (api *API) validateTokens(tokenIds []*bigint.BigInt) error {
|
||||||
if len(tokenIds) == 0 {
|
if len(tokenIds) == 0 {
|
||||||
return 0, errors.New("token list is empty")
|
return errors.New("token list is empty")
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) validateBurnAmount(ctx context.Context, burnAmount *bigint.BigInt, chainID uint64, contractAddress string) error {
|
||||||
|
if burnAmount.Cmp(big.NewInt(0)) <= 0 {
|
||||||
|
return errors.New("burnAmount is less than 0")
|
||||||
|
}
|
||||||
|
remainingSupply, err := api.RemainingSupply(ctx, chainID, contractAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if burnAmount.Cmp(remainingSupply) > 1 {
|
||||||
|
return errors.New("burnAmount is bigger than remaining amount")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) estimateMethod(ctx context.Context, chainID uint64, contractAddress 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())
|
||||||
|
@ -284,12 +359,7 @@ func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contract
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempTokenIds []*big.Int
|
data, err := collectiblesABI.Pack(methodName, args...)
|
||||||
for _, v := range tokenIds {
|
|
||||||
tempTokenIds = append(tempTokenIds, v.Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := collectiblesABI.Pack("remoteBurn", tempTokenIds)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -298,6 +368,7 @@ func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contract
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
toAddr := common.HexToAddress(contractAddress)
|
toAddr := common.HexToAddress(contractAddress)
|
||||||
fromAddr := common.HexToAddress(ownerAddr)
|
fromAddr := common.HexToAddress(ownerAddr)
|
||||||
|
|
||||||
|
@ -307,7 +378,6 @@ func (api *API) EstimateRemoteBurn(ctx context.Context, chainID uint64, contract
|
||||||
Value: big.NewInt(0),
|
Value: big.NewInt(0),
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
|
|
||||||
estimate, err := ethClient.EstimateGas(ctx, callMsg)
|
estimate, err := ethClient.EstimateGas(ctx, callMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
|
@ -1309,8 +1309,12 @@ func (api *PublicAPI) AddCommunityToken(token *communities.CommunityToken) (*com
|
||||||
return api.service.messenger.AddCommunityToken(token)
|
return api.service.messenger.AddCommunityToken(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PublicAPI) UpdateCommunityTokenState(contractAddress string, deployState communities.DeployState) error {
|
func (api *PublicAPI) UpdateCommunityTokenState(chainID int, contractAddress string, deployState communities.DeployState) error {
|
||||||
return api.service.messenger.UpdateCommunityTokenState(contractAddress, deployState)
|
return api.service.messenger.UpdateCommunityTokenState(chainID, contractAddress, deployState)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *PublicAPI) UpdateCommunityTokenSupply(chainID int, contractAddress string, supply int) error {
|
||||||
|
return api.service.messenger.UpdateCommunityTokenSupply(chainID, contractAddress, supply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PublicAPI) ToggleCollapsedCommunityCategory(request *requests.ToggleCollapsedCommunityCategory) error {
|
func (api *PublicAPI) ToggleCollapsedCommunityCategory(request *requests.ToggleCollapsedCommunityCategory) error {
|
||||||
|
|
|
@ -89,6 +89,7 @@ const (
|
||||||
CollectibleDeployment PendingTrxType = "CollectibleDeployment"
|
CollectibleDeployment PendingTrxType = "CollectibleDeployment"
|
||||||
CollectibleAirdrop PendingTrxType = "CollectibleAirdrop"
|
CollectibleAirdrop PendingTrxType = "CollectibleAirdrop"
|
||||||
CollectibleRemoteSelfDestruct PendingTrxType = "CollectibleRemoteSelfDestruct"
|
CollectibleRemoteSelfDestruct PendingTrxType = "CollectibleRemoteSelfDestruct"
|
||||||
|
CollectibleBurn PendingTrxType = "CollectibleBurn"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PendingTransaction struct {
|
type PendingTransaction struct {
|
||||||
|
|
Loading…
Reference in New Issue