github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/token_associate_transaction.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  	"time"
    25  
    26  	"github.com/hashgraph/hedera-protobufs-go/services"
    27  )
    28  
    29  // TokenAssociateTransaction Associates the provided account with the provided tokens. Must be signed by the provided Account's key.
    30  // If the provided account is not found, the transaction will resolve to
    31  // INVALID_ACCOUNT_ID.
    32  // If the provided account has been deleted, the transaction will resolve to
    33  // ACCOUNT_DELETED.
    34  // If any of the provided tokens is not found, the transaction will resolve to
    35  // INVALID_TOKEN_REF.
    36  // If any of the provided tokens has been deleted, the transaction will resolve to
    37  // TOKEN_WAS_DELETED.
    38  // If an association between the provided account and any of the tokens already exists, the
    39  // transaction will resolve to
    40  // TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT.
    41  // If the provided account's associations count exceed the constraint of maximum token
    42  // associations per account, the transaction will resolve to
    43  // TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED.
    44  // On success, associations between the provided account and tokens are made and the account is
    45  // ready to interact with the tokens.
    46  type TokenAssociateTransaction struct {
    47  	Transaction
    48  	accountID *AccountID
    49  	tokens    []TokenID
    50  }
    51  
    52  // NewTokenAssociateTransaction creates TokenAssociateTransaction which associates the provided account with the provided tokens.
    53  // Must be signed by the provided Account's key.
    54  // If the provided account is not found, the transaction will resolve to
    55  // INVALID_ACCOUNT_ID.
    56  // If the provided account has been deleted, the transaction will resolve to
    57  // ACCOUNT_DELETED.
    58  // If any of the provided tokens is not found, the transaction will resolve to
    59  // INVALID_TOKEN_REF.
    60  // If any of the provided tokens has been deleted, the transaction will resolve to
    61  // TOKEN_WAS_DELETED.
    62  // If an association between the provided account and any of the tokens already exists, the
    63  // transaction will resolve to
    64  // TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT.
    65  // If the provided account's associations count exceed the constraint of maximum token
    66  // associations per account, the transaction will resolve to
    67  // TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED.
    68  // On success, associations between the provided account and tokens are made and the account is
    69  // ready to interact with the tokens.
    70  func NewTokenAssociateTransaction() *TokenAssociateTransaction {
    71  	tx := TokenAssociateTransaction{
    72  		Transaction: _NewTransaction(),
    73  	}
    74  
    75  	tx._SetDefaultMaxTransactionFee(NewHbar(5))
    76  
    77  	return &tx
    78  }
    79  
    80  func _TokenAssociateTransactionFromProtobuf(tx Transaction, pb *services.TransactionBody) *TokenAssociateTransaction {
    81  	tokens := make([]TokenID, 0)
    82  	for _, token := range pb.GetTokenAssociate().Tokens {
    83  		if tokenID := _TokenIDFromProtobuf(token); tokenID != nil {
    84  			tokens = append(tokens, *tokenID)
    85  		}
    86  	}
    87  
    88  	return &TokenAssociateTransaction{
    89  		Transaction: tx,
    90  		accountID:   _AccountIDFromProtobuf(pb.GetTokenAssociate().GetAccount()),
    91  		tokens:      tokens,
    92  	}
    93  }
    94  
    95  // SetAccountID Sets the account to be associated with the provided tokens
    96  func (tx *TokenAssociateTransaction) SetAccountID(accountID AccountID) *TokenAssociateTransaction {
    97  	tx._RequireNotFrozen()
    98  	tx.accountID = &accountID
    99  	return tx
   100  }
   101  
   102  // GetAccountID returns the account to be associated with the provided tokens
   103  func (tx *TokenAssociateTransaction) GetAccountID() AccountID {
   104  	if tx.accountID == nil {
   105  		return AccountID{}
   106  	}
   107  
   108  	return *tx.accountID
   109  }
   110  
   111  // SetTokenIDs Sets the tokens to be associated with the provided account
   112  func (tx *TokenAssociateTransaction) SetTokenIDs(ids ...TokenID) *TokenAssociateTransaction {
   113  	tx._RequireNotFrozen()
   114  	tx.tokens = make([]TokenID, len(ids))
   115  	copy(tx.tokens, ids)
   116  
   117  	return tx
   118  }
   119  
   120  // AddTokenID Adds the token to a token list to be associated with the provided account
   121  func (tx *TokenAssociateTransaction) AddTokenID(id TokenID) *TokenAssociateTransaction {
   122  	tx._RequireNotFrozen()
   123  	if tx.tokens == nil {
   124  		tx.tokens = make([]TokenID, 0)
   125  	}
   126  
   127  	tx.tokens = append(tx.tokens, id)
   128  
   129  	return tx
   130  }
   131  
   132  // GetTokenIDs returns the tokens to be associated with the provided account
   133  func (tx *TokenAssociateTransaction) GetTokenIDs() []TokenID {
   134  	tokenIDs := make([]TokenID, len(tx.tokens))
   135  	copy(tokenIDs, tx.tokens)
   136  
   137  	return tokenIDs
   138  }
   139  
   140  // ---- Required Interfaces ---- //
   141  
   142  // Sign uses the provided privateKey to sign the transaction.
   143  func (tx *TokenAssociateTransaction) Sign(privateKey PrivateKey) *TokenAssociateTransaction {
   144  	tx.Transaction.Sign(privateKey)
   145  	return tx
   146  }
   147  
   148  // SignWithOperator signs the transaction with client's operator privateKey.
   149  func (tx *TokenAssociateTransaction) SignWithOperator(client *Client) (*TokenAssociateTransaction, error) {
   150  	_, err := tx.Transaction.signWithOperator(client, tx)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  	return tx, nil
   155  }
   156  
   157  // SignWith executes the TransactionSigner and adds the resulting signature data to the Transaction's signature map
   158  // with the publicKey as the map key.
   159  func (tx *TokenAssociateTransaction) SignWith(
   160  	publicKey PublicKey,
   161  	signer TransactionSigner,
   162  ) *TokenAssociateTransaction {
   163  	tx.Transaction.SignWith(publicKey, signer)
   164  	return tx
   165  }
   166  
   167  // AddSignature adds a signature to the transaction.
   168  func (tx *TokenAssociateTransaction) AddSignature(publicKey PublicKey, signature []byte) *TokenAssociateTransaction {
   169  	tx.Transaction.AddSignature(publicKey, signature)
   170  	return tx
   171  }
   172  
   173  // When execution is attempted, a single attempt will timeout when this deadline is reached. (The SDK may subsequently retry the execution.)
   174  func (tx *TokenAssociateTransaction) SetGrpcDeadline(deadline *time.Duration) *TokenAssociateTransaction {
   175  	tx.Transaction.SetGrpcDeadline(deadline)
   176  	return tx
   177  }
   178  
   179  func (tx *TokenAssociateTransaction) Freeze() (*TokenAssociateTransaction, error) {
   180  	return tx.FreezeWith(nil)
   181  }
   182  
   183  func (tx *TokenAssociateTransaction) FreezeWith(client *Client) (*TokenAssociateTransaction, error) {
   184  	_, err := tx.Transaction.freezeWith(client, tx)
   185  	return tx, err
   186  }
   187  
   188  // SetMaxTransactionFee sets the max transaction fee for this TokenAssociateTransaction.
   189  func (tx *TokenAssociateTransaction) SetMaxTransactionFee(fee Hbar) *TokenAssociateTransaction {
   190  	tx.Transaction.SetMaxTransactionFee(fee)
   191  	return tx
   192  }
   193  
   194  // SetRegenerateTransactionID sets if transaction IDs should be regenerated when `TRANSACTION_EXPIRED` is received
   195  func (tx *TokenAssociateTransaction) SetRegenerateTransactionID(regenerateTransactionID bool) *TokenAssociateTransaction {
   196  	tx.Transaction.SetRegenerateTransactionID(regenerateTransactionID)
   197  	return tx
   198  }
   199  
   200  // SetTransactionMemo sets the memo for this TokenAssociateTransaction.
   201  func (tx *TokenAssociateTransaction) SetTransactionMemo(memo string) *TokenAssociateTransaction {
   202  	tx.Transaction.SetTransactionMemo(memo)
   203  	return tx
   204  }
   205  
   206  // SetTransactionValidDuration sets the valid duration for this TokenAssociateTransaction.
   207  func (tx *TokenAssociateTransaction) SetTransactionValidDuration(duration time.Duration) *TokenAssociateTransaction {
   208  	tx.Transaction.SetTransactionValidDuration(duration)
   209  	return tx
   210  }
   211  
   212  // ToBytes serialise the tx to bytes, no matter if it is signed (locked), or not
   213  func (tx *TokenAssociateTransaction) ToBytes() ([]byte, error) {
   214  	bytes, err := tx.Transaction.toBytes(tx)
   215  	if err != nil {
   216  		return nil, err
   217  	}
   218  	return bytes, nil
   219  }
   220  
   221  // SetTransactionID sets the TransactionID for this TokenAssociateTransaction.
   222  func (tx *TokenAssociateTransaction) SetTransactionID(transactionID TransactionID) *TokenAssociateTransaction {
   223  	tx.Transaction.SetTransactionID(transactionID)
   224  	return tx
   225  }
   226  
   227  // SetNodeAccountIDs sets the _Node AccountID for this TokenAssociateTransaction.
   228  func (tx *TokenAssociateTransaction) SetNodeAccountIDs(nodeID []AccountID) *TokenAssociateTransaction {
   229  	tx.Transaction.SetNodeAccountIDs(nodeID)
   230  	return tx
   231  }
   232  
   233  // SetMaxRetry sets the max number of errors before execution will fail.
   234  func (tx *TokenAssociateTransaction) SetMaxRetry(count int) *TokenAssociateTransaction {
   235  	tx.Transaction.SetMaxRetry(count)
   236  	return tx
   237  }
   238  
   239  // SetMaxBackoff The maximum amount of time to wait between retries.
   240  // Every retry attempt will increase the wait time exponentially until it reaches this time.
   241  func (tx *TokenAssociateTransaction) SetMaxBackoff(max time.Duration) *TokenAssociateTransaction {
   242  	tx.Transaction.SetMaxBackoff(max)
   243  	return tx
   244  }
   245  
   246  // SetMinBackoff sets the minimum amount of time to wait between retries.
   247  func (tx *TokenAssociateTransaction) SetMinBackoff(min time.Duration) *TokenAssociateTransaction {
   248  	tx.Transaction.SetMinBackoff(min)
   249  	return tx
   250  }
   251  
   252  func (tx *TokenAssociateTransaction) SetLogLevel(level LogLevel) *TokenAssociateTransaction {
   253  	tx.Transaction.SetLogLevel(level)
   254  	return tx
   255  }
   256  
   257  func (tx *TokenAssociateTransaction) Execute(client *Client) (TransactionResponse, error) {
   258  	return tx.Transaction.execute(client, tx)
   259  }
   260  
   261  func (tx *TokenAssociateTransaction) Schedule() (*ScheduleCreateTransaction, error) {
   262  	return tx.Transaction.schedule(tx)
   263  }
   264  
   265  // ----------- Overridden functions ----------------
   266  
   267  func (tx *TokenAssociateTransaction) getName() string {
   268  	return "TokenAssociateTransaction"
   269  }
   270  
   271  func (tx *TokenAssociateTransaction) validateNetworkOnIDs(client *Client) error {
   272  	if client == nil || !client.autoValidateChecksums {
   273  		return nil
   274  	}
   275  
   276  	if tx.accountID != nil {
   277  		if err := tx.accountID.ValidateChecksum(client); err != nil {
   278  			return err
   279  		}
   280  	}
   281  
   282  	for _, tokenID := range tx.tokens {
   283  		if err := tokenID.ValidateChecksum(client); err != nil {
   284  			return err
   285  		}
   286  	}
   287  
   288  	return nil
   289  }
   290  
   291  func (tx *TokenAssociateTransaction) build() *services.TransactionBody {
   292  	body := tx.buildProtoBody()
   293  
   294  	return &services.TransactionBody{
   295  		TransactionFee:           tx.transactionFee,
   296  		Memo:                     tx.Transaction.memo,
   297  		TransactionValidDuration: _DurationToProtobuf(tx.GetTransactionValidDuration()),
   298  		TransactionID:            tx.transactionID._ToProtobuf(),
   299  		Data: &services.TransactionBody_TokenAssociate{
   300  			TokenAssociate: body,
   301  		},
   302  	}
   303  }
   304  
   305  func (tx *TokenAssociateTransaction) buildScheduled() (*services.SchedulableTransactionBody, error) {
   306  	return &services.SchedulableTransactionBody{
   307  		TransactionFee: tx.transactionFee,
   308  		Memo:           tx.Transaction.memo,
   309  		Data: &services.SchedulableTransactionBody_TokenAssociate{
   310  			TokenAssociate: tx.buildProtoBody(),
   311  		},
   312  	}, nil
   313  }
   314  
   315  func (tx *TokenAssociateTransaction) buildProtoBody() *services.TokenAssociateTransactionBody {
   316  	body := &services.TokenAssociateTransactionBody{}
   317  	if tx.accountID != nil {
   318  		body.Account = tx.accountID._ToProtobuf()
   319  	}
   320  
   321  	if len(tx.tokens) > 0 {
   322  		for _, tokenID := range tx.tokens {
   323  			if body.Tokens == nil {
   324  				body.Tokens = make([]*services.TokenID, 0)
   325  			}
   326  			body.Tokens = append(body.Tokens, tokenID._ToProtobuf())
   327  		}
   328  	}
   329  	return body
   330  }
   331  
   332  func (tx *TokenAssociateTransaction) getMethod(channel *_Channel) _Method {
   333  	return _Method{
   334  		transaction: channel._GetToken().AssociateTokens,
   335  	}
   336  }
   337  func (tx *TokenAssociateTransaction) _ConstructScheduleProtobuf() (*services.SchedulableTransactionBody, error) {
   338  	return tx.buildScheduled()
   339  }