Skip to content

Commit

Permalink
feat: start Token*Transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
janaakhterov committed Oct 19, 2020
1 parent e5db007 commit 7dee0a2
Show file tree
Hide file tree
Showing 14 changed files with 2,914 additions and 0 deletions.
9 changes: 9 additions & 0 deletions channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type channel struct {
topic proto.ConsensusServiceClient
freeze proto.FreezeServiceClient
network proto.NetworkServiceClient
token proto.TokenServiceClient
client *grpc.ClientConn
}

Expand Down Expand Up @@ -68,3 +69,11 @@ func (channel channel) getNetwork() proto.NetworkServiceClient {

return channel.network
}

func (channel channel) getToken() proto.TokenServiceClient {
if channel.token == nil {
channel.token = proto.NewTokenServiceClient(channel.client)
}

return channel.token
}
241 changes: 241 additions & 0 deletions token_associate_transaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
package hedera

import (
"time"

"github.com/hashgraph/hedera-sdk-go/proto"
)

// Associates the provided account with the provided tokens. Must be signed by the provided Account's key.
// If the provided account is not found, the transaction will resolve to
// INVALID_ACCOUNT_ID.
// If the provided account has been deleted, the transaction will resolve to
// ACCOUNT_DELETED.
// If any of the provided tokens is not found, the transaction will resolve to
// INVALID_TOKEN_REF.
// If any of the provided tokens has been deleted, the transaction will resolve to
// TOKEN_WAS_DELETED.
// If an association between the provided account and any of the tokens already exists, the
// transaction will resolve to
// TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT.
// If the provided account's associations count exceed the constraint of maximum token
// associations per account, the transaction will resolve to
// TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED.
// On success, associations between the provided account and tokens are made and the account is
// ready to interact with the tokens.
type TokenAssociateTransaction struct {
Transaction
pb *proto.TokenAssociateTransactionBody
}

func NewTokenAssociateTransaction() *TokenAssociateTransaction {
pb := &proto.TokenAssociateTransactionBody{}

transaction := TokenAssociateTransaction{
pb: pb,
Transaction: newTransaction(),
}

return &transaction
}

// The account to be associated with the provided tokens
func (transaction *TokenAssociateTransaction) SetAccountID(accountID AccountID) *TokenAssociateTransaction {
transaction.pb.Account = accountID.toProtobuf()
return transaction
}

// The tokens to be associated with the provided account
func (transaction *TokenAssociateTransaction) SetTokenIDs(tokenIDs ...TokenID) *TokenAssociateTransaction {
transaction.pb.Tokens = make([]*proto.TokenID, len(tokenIDs))

for i, tokenID := range tokenIDs {
transaction.pb.Tokens[i] = tokenID.toProtobuf()
}

return transaction
}

//
// The following methods must be copy-pasted/overriden at the bottom of **every** _transaction.go file
// We override the embedded fluent setter methods to return the outer type
//

func tokenAssociateTransaction_getMethod(request request, channel *channel) method {
return method{
transaction: channel.getToken().AssociateTokens,
}
}

func (transaction *TokenAssociateTransaction) IsFrozen() bool {
return transaction.isFrozen()
}

// Sign uses the provided privateKey to sign the transaction.
func (transaction *TokenAssociateTransaction) Sign(
privateKey PrivateKey,
) *TokenAssociateTransaction {
return transaction.SignWith(privateKey.PublicKey(), privateKey.Sign)
}

func (transaction *TokenAssociateTransaction) SignWithOperator(
client *Client,
) (*TokenAssociateTransaction, error) {
// If the transaction is not signed by the operator, we need
// to sign the transaction with the operator

if client.operator == nil {
return nil, errClientOperatorSigning
}

if !transaction.IsFrozen() {
transaction.FreezeWith(client)
}

return transaction.SignWith(client.operator.publicKey, client.operator.signer), nil
}

// SignWith executes the TransactionSigner and adds the resulting signature data to the Transaction's signature map
// with the publicKey as the map key.
func (transaction *TokenAssociateTransaction) SignWith(
publicKey PublicKey,
signer TransactionSigner,
) *TokenAssociateTransaction {
if !transaction.IsFrozen() {
transaction.Freeze()
}

if transaction.keyAlreadySigned(publicKey) {
return transaction
}

for index := 0; index < len(transaction.transactions); index++ {
signature := signer(transaction.transactions[index].GetBodyBytes())

transaction.signatures[index].SigPair = append(
transaction.signatures[index].SigPair,
publicKey.toSignaturePairProtobuf(signature),
)
}

return transaction
}

// Execute executes the Transaction with the provided client
func (transaction *TokenAssociateTransaction) Execute(
client *Client,
) (TransactionResponse, error) {
if !transaction.IsFrozen() {
transaction.FreezeWith(client)
}

transactionID := transaction.id

if !client.GetOperatorID().isZero() && client.GetOperatorID().equals(transactionID.TokenID) {
transaction.SignWith(
client.GetOperatorKey(),
client.operator.signer,
)
}

resp, err := execute(
client,
request{
transaction: &transaction.Transaction,
},
transaction_shouldRetry,
transaction_makeRequest,
transaction_advanceRequest,
transaction_getNodeId,
tokenAssociateTransaction_getMethod,
transaction_mapResponseStatus,
transaction_mapResponse,
)

if err != nil {
return TransactionResponse{}, err
}

return TransactionResponse{
TransactionID: transaction.id,
NodeID: resp.transaction.NodeID,
}, nil
}

func (transaction *TokenAssociateTransaction) onFreeze(
pbBody *proto.TransactionBody,
) bool {
pbBody.Data = &proto.TransactionBody_TokenAssociate{
TokenAssociate: transaction.pb,
}

return true
}

func (transaction *TokenAssociateTransaction) Freeze() (*TokenAssociateTransaction, error) {
return transaction.FreezeWith(nil)
}

func (transaction *TokenAssociateTransaction) FreezeWith(client *Client) (*TokenAssociateTransaction, error) {
transaction.initFee(client)
if err := transaction.initTransactionID(client); err != nil {
return transaction, err
}

if !transaction.onFreeze(transaction.pbBody) {
return transaction, nil
}

return transaction, transaction_freezeWith(&transaction.Transaction, client)
}

func (transaction *TokenAssociateTransaction) GetMaxTransactionFee() Hbar {
return transaction.Transaction.GetMaxTransactionFee()
}

// SetMaxTransactionFee sets the max transaction fee for this TokenAssociateTransaction.
func (transaction *TokenAssociateTransaction) SetMaxTransactionFee(fee Hbar) *TokenAssociateTransaction {
transaction.Transaction.SetMaxTransactionFee(fee)
return transaction
}

func (transaction *TokenAssociateTransaction) GetTransactionMemo() string {
return transaction.Transaction.GetTransactionMemo()
}

// SetTransactionMemo sets the memo for this TokenAssociateTransaction.
func (transaction *TokenAssociateTransaction) SetTransactionMemo(memo string) *TokenAssociateTransaction {
transaction.Transaction.SetTransactionMemo(memo)
return transaction
}

func (transaction *TokenAssociateTransaction) GetTransactionValidDuration() time.Duration {
return transaction.Transaction.GetTransactionValidDuration()
}

// SetTransactionValidDuration sets the valid duration for this TokenAssociateTransaction.
func (transaction *TokenAssociateTransaction) SetTransactionValidDuration(duration time.Duration) *TokenAssociateTransaction {
transaction.Transaction.SetTransactionValidDuration(duration)
return transaction
}

func (transaction *TokenAssociateTransaction) GetTransactionID() TransactionID {
return transaction.Transaction.GetTransactionID()
}

// SetTransactionID sets the TransactionID for this TokenAssociateTransaction.
func (transaction *TokenAssociateTransaction) SetTransactionID(transactionID TransactionID) *TokenAssociateTransaction {
transaction.id = transactionID
transaction.Transaction.SetTransactionID(transactionID)
return transaction
}

func (transaction *TokenAssociateTransaction) GetNodeID() AccountID {
return transaction.Transaction.GetNodeID()
}

// SetNodeTokenID sets the node TokenID for this TokenAssociateTransaction.
func (transaction *TokenAssociateTransaction) SetNodeAccountID(nodeID AccountID) *TokenAssociateTransaction {
transaction.Transaction.SetNodeAccountID(nodeID)
return transaction
}
Loading

0 comments on commit 7dee0a2

Please sign in to comment.