github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/token_id.go (about)

     1  package hedera
     2  
     3  /*-
     4   *
     5   * Hedera Go SDK
     6   *
     7   * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
     8   *
     9   * Licensed under the Apache License, Version 2.0 (the "License");
    10   * you may not use this file except in compliance with the License.
    11   * You may obtain a copy of the License at
    12   *
    13   *      http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing, software
    16   * distributed under the License is distributed on an "AS IS" BASIS,
    17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18   * See the License for the specific language governing permissions and
    19   * limitations under the License.
    20   *
    21   */
    22  
    23  import (
    24  	"fmt"
    25  
    26  	"github.com/pkg/errors"
    27  
    28  	"github.com/hashgraph/hedera-protobufs-go/services"
    29  	protobuf "google.golang.org/protobuf/proto"
    30  )
    31  
    32  // TokenID is the ID for a Hedera token
    33  type TokenID struct {
    34  	Shard    uint64
    35  	Realm    uint64
    36  	Token    uint64
    37  	checksum *string
    38  }
    39  
    40  func _TokenIDFromProtobuf(tokenID *services.TokenID) *TokenID {
    41  	if tokenID == nil {
    42  		return nil
    43  	}
    44  
    45  	return &TokenID{
    46  		Shard: uint64(tokenID.ShardNum),
    47  		Realm: uint64(tokenID.RealmNum),
    48  		Token: uint64(tokenID.TokenNum),
    49  	}
    50  }
    51  
    52  func (id *TokenID) _ToProtobuf() *services.TokenID {
    53  	return &services.TokenID{
    54  		ShardNum: int64(id.Shard),
    55  		RealmNum: int64(id.Realm),
    56  		TokenNum: int64(id.Token),
    57  	}
    58  }
    59  
    60  // String returns a string representation of the TokenID formatted as `Shard.Realm.TokenID` (for example "0.0.3")
    61  func (id TokenID) String() string {
    62  	return fmt.Sprintf("%d.%d.%d", id.Shard, id.Realm, id.Token)
    63  }
    64  
    65  // ToStringWithChecksum returns a string representation of the TokenID formatted as `Shard.Realm.TokenID-Checksum` (for example "0.0.3-abcd")
    66  func (id TokenID) ToStringWithChecksum(client Client) (string, error) {
    67  	if client.GetNetworkName() == nil && client.GetLedgerID() == nil {
    68  		return "", errNetworkNameMissing
    69  	}
    70  	var checksum _ParseAddressResult
    71  	var err error
    72  	if client.network.ledgerID != nil {
    73  		checksum, err = _ChecksumParseAddress(client.GetLedgerID(), fmt.Sprintf("%d.%d.%d", id.Shard, id.Realm, id.Token))
    74  	}
    75  	if err != nil {
    76  		return "", err
    77  	}
    78  	return fmt.Sprintf("%d.%d.%d-%s", id.Shard, id.Realm, id.Token, checksum.correctChecksum), nil
    79  }
    80  
    81  // ToBytes returns a byte array representation of the TokenID
    82  func (id TokenID) ToBytes() []byte {
    83  	data, err := protobuf.Marshal(id._ToProtobuf())
    84  	if err != nil {
    85  		return make([]byte, 0)
    86  	}
    87  
    88  	return data
    89  }
    90  
    91  // TokenIDFromBytes returns a TokenID from a byte array
    92  func TokenIDFromBytes(data []byte) (TokenID, error) {
    93  	if data == nil {
    94  		return TokenID{}, errByteArrayNull
    95  	}
    96  	pb := services.TokenID{}
    97  	err := protobuf.Unmarshal(data, &pb)
    98  	if err != nil {
    99  		return TokenID{}, err
   100  	}
   101  
   102  	return *_TokenIDFromProtobuf(&pb), nil
   103  }
   104  
   105  // NftID constructs an NftID from a TokenID and a serial number
   106  func (id *TokenID) Nft(serial int64) NftID {
   107  	return NftID{
   108  		TokenID:      *id,
   109  		SerialNumber: serial,
   110  	}
   111  }
   112  
   113  // TokenIDFromString constructs an TokenID from a string formatted as
   114  // `Shard.Realm.TokenID` (for example "0.0.3")
   115  func TokenIDFromString(data string) (TokenID, error) {
   116  	shard, realm, num, checksum, err := _IdFromString(data)
   117  	if err != nil {
   118  		return TokenID{}, err
   119  	}
   120  
   121  	return TokenID{
   122  		Shard:    uint64(shard),
   123  		Realm:    uint64(realm),
   124  		Token:    uint64(num),
   125  		checksum: checksum,
   126  	}, nil
   127  }
   128  
   129  // Verify that the client has a valid checksum.
   130  func (id *TokenID) ValidateChecksum(client *Client) error {
   131  	if !id._IsZero() && client != nil {
   132  		var tempChecksum _ParseAddressResult
   133  		var err error
   134  		tempChecksum, err = _ChecksumParseAddress(client.GetLedgerID(), fmt.Sprintf("%d.%d.%d", id.Shard, id.Realm, id.Token))
   135  		if err != nil {
   136  			return err
   137  		}
   138  		err = _ChecksumVerify(tempChecksum.status)
   139  		if err != nil {
   140  			return err
   141  		}
   142  		if id.checksum == nil {
   143  			return errChecksumMissing
   144  		}
   145  		if tempChecksum.correctChecksum != *id.checksum {
   146  			networkName := NetworkNameOther
   147  			if client.network.ledgerID != nil {
   148  				networkName, _ = client.network.ledgerID.ToNetworkName()
   149  			}
   150  			return errors.New(fmt.Sprintf("network mismatch or wrong checksum given, given checksum: %s, correct checksum %s, network: %s",
   151  				*id.checksum,
   152  				tempChecksum.correctChecksum,
   153  				networkName))
   154  		}
   155  	}
   156  
   157  	return nil
   158  }
   159  
   160  // Deprecated - use ValidateChecksum instead
   161  func (id *TokenID) Validate(client *Client) error {
   162  	return id.ValidateChecksum(client)
   163  }
   164  
   165  // TokenIDFromSolidityAddress constructs a TokenID from a string
   166  // representation of a _Solidity address
   167  func TokenIDFromSolidityAddress(s string) (TokenID, error) {
   168  	shard, realm, token, err := _IdFromSolidityAddress(s)
   169  	if err != nil {
   170  		return TokenID{}, err
   171  	}
   172  
   173  	return TokenID{
   174  		Shard:    shard,
   175  		Realm:    realm,
   176  		Token:    token,
   177  		checksum: nil,
   178  	}, nil
   179  }
   180  
   181  // ToSolidityAddress returns the string representation of the TokenID as a
   182  // _Solidity address.
   183  func (id TokenID) ToSolidityAddress() string {
   184  	return _IdToSolidityAddress(id.Shard, id.Realm, id.Token)
   185  }
   186  
   187  func (id TokenID) _IsZero() bool {
   188  	return id.Shard == 0 && id.Realm == 0 && id.Token == 0
   189  }
   190  
   191  // equals returns true if this TokenID and the given TokenID are identical
   192  func (id TokenID) equals(other TokenID) bool {
   193  	return id.Shard == other.Shard && id.Realm == other.Realm
   194  }
   195  
   196  // Compare compares two TokenIDs
   197  func (id TokenID) Compare(given TokenID) int {
   198  	if id.Shard > given.Shard { //nolint
   199  		return 1
   200  	} else if id.Shard < given.Shard {
   201  		return -1
   202  	}
   203  
   204  	if id.Realm > given.Realm { //nolint
   205  		return 1
   206  	} else if id.Realm < given.Realm {
   207  		return -1
   208  	}
   209  
   210  	if id.Token > given.Token { //nolint
   211  		return 1
   212  	} else if id.Token < given.Token {
   213  		return -1
   214  	} else { //nolint
   215  		return 0
   216  	}
   217  }