github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/ethereum_flow.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 "github.com/pkg/errors" 24 25 // Execute an Ethereum transaction on Hedera 26 type EthereumFlow struct { 27 Transaction 28 ethereumData *EthereumTransactionData 29 callDataFileID *FileID 30 maxGasAllowance *Hbar 31 nodeAccountIDs []AccountID 32 } 33 34 // Execute an Ethereum transaction on Hedera 35 func NewEthereumFlow() *EthereumFlow { 36 tx := EthereumFlow{ 37 Transaction: _NewTransaction(), 38 } 39 40 tx._SetDefaultMaxTransactionFee(NewHbar(20)) 41 42 return &tx 43 } 44 45 // SetEthereumData sets the raw Ethereum transaction. 46 func (transaction *EthereumFlow) SetEthereumData(data *EthereumTransactionData) *EthereumFlow { 47 transaction._RequireNotFrozen() 48 transaction.ethereumData = data 49 return transaction 50 } 51 52 // SetEthereumDataBytes sets the raw Ethereum transaction. 53 func (transaction *EthereumFlow) SetEthereumDataBytes(data []byte) *EthereumFlow { 54 transaction._RequireNotFrozen() 55 temp, err := EthereumTransactionDataFromBytes(data) 56 if err != nil { 57 panic(err) 58 } 59 transaction.ethereumData = temp 60 return transaction 61 } 62 63 // GetEthreumData returns the data of the Ethereum transaction 64 func (transaction *EthereumFlow) GetEthereumData() *EthereumTransactionData { 65 return transaction.ethereumData 66 } 67 68 // SetCallDataFileID sets the file ID containing the call data. 69 func (transaction *EthereumFlow) SetCallDataFileID(callData FileID) *EthereumFlow { 70 transaction._RequireNotFrozen() 71 transaction.callDataFileID = &callData 72 return transaction 73 } 74 75 // GetCallDataFileID returns the file ID containing the call data. 76 func (transaction *EthereumFlow) GetCallDataFileID() FileID { 77 if transaction.callDataFileID == nil { 78 return FileID{} 79 } 80 81 return *transaction.callDataFileID 82 } 83 84 // SetMaxGasAllowance sets the maximum gas allowance for the transaction. 85 func (transaction *EthereumFlow) SetMaxGasAllowance(max Hbar) *EthereumFlow { 86 transaction._RequireNotFrozen() 87 transaction.maxGasAllowance = &max 88 return transaction 89 } 90 91 // GetMaxGasAllowance returns the maximum gas allowance for the transaction. 92 func (transaction *EthereumFlow) GetMaxGasAllowance() Hbar { 93 if transaction.maxGasAllowance == nil { 94 return Hbar{} 95 } 96 97 return *transaction.maxGasAllowance 98 } 99 100 // SetNodeAccountIDs sets the node account IDs for this Ethereum transaction. 101 func (transaction *EthereumFlow) SetNodeAccountIDs(nodes []AccountID) *EthereumFlow { 102 transaction._RequireNotFrozen() 103 transaction.nodeAccountIDs = nodes 104 return transaction 105 } 106 107 // GetNodeAccountIDs returns the node account IDs for this Ethereum transaction. 108 func (transaction *EthereumFlow) GetNodeAccountIDs() []AccountID { 109 return transaction.nodeAccountIDs 110 } 111 112 func (transaction *EthereumFlow) _CreateFile(callData []byte, client *Client) (FileID, error) { 113 fileCreate := NewFileCreateTransaction() 114 if len(transaction.nodeAccountIDs) > 0 { 115 fileCreate.SetNodeAccountIDs(transaction.nodeAccountIDs) 116 } 117 118 if len(callData) < 4097 { 119 resp, err := fileCreate. 120 SetContents(callData). 121 Execute(client) 122 if err != nil { 123 return FileID{}, err 124 } 125 126 receipt, err := resp.GetReceipt(client) 127 if err != nil { 128 return FileID{}, err 129 } 130 131 return *receipt.FileID, nil 132 } 133 134 resp, err := fileCreate. 135 SetContents(callData[:4097]). 136 Execute(client) 137 if err != nil { 138 return FileID{}, err 139 } 140 141 receipt, err := resp.GetReceipt(client) 142 if err != nil { 143 return FileID{}, err 144 } 145 146 fileID := *receipt.FileID 147 148 resp, err = NewFileAppendTransaction(). 149 SetFileID(fileID). 150 SetContents(callData[4097:]). 151 Execute(client) 152 if err != nil { 153 return FileID{}, err 154 } 155 156 _, err = resp.GetReceipt(client) 157 if err != nil { 158 return FileID{}, err 159 } 160 161 return fileID, nil 162 } 163 164 // Execute executes the Transaction with the provided client 165 func (transaction *EthereumFlow) Execute(client *Client) (TransactionResponse, error) { 166 if transaction.ethereumData == nil { 167 return TransactionResponse{}, errors.New("cannot submit ethereum transaction with no ethereum data") 168 } 169 170 ethereumTransaction := NewEthereumTransaction() 171 if len(transaction.nodeAccountIDs) > 0 { 172 ethereumTransaction.SetNodeAccountIDs(transaction.nodeAccountIDs) 173 } 174 dataBytes, err := transaction.ethereumData.ToBytes() 175 if err != nil { 176 return TransactionResponse{}, err 177 } 178 179 if transaction.maxGasAllowance != nil { 180 ethereumTransaction.SetMaxGasAllowanceHbar(*transaction.maxGasAllowance) 181 } 182 183 if transaction.callDataFileID != nil { //nolint 184 if len(transaction.ethereumData._GetData()) != 0 { 185 return TransactionResponse{}, errors.New("call data file ID provided, but ethereum data already contains call data") 186 } 187 188 ethereumTransaction. 189 SetEthereumData(dataBytes). 190 SetCallDataFileID(*transaction.callDataFileID) 191 } else if len(dataBytes) <= 5120 { 192 ethereumTransaction. 193 SetEthereumData(dataBytes) 194 } else { 195 fileID, err := transaction. 196 _CreateFile(dataBytes, client) 197 if err != nil { 198 return TransactionResponse{}, err 199 } 200 201 transaction.ethereumData._SetData([]byte{}) 202 203 ethereumTransaction. 204 SetEthereumData(dataBytes). 205 SetCallDataFileID(fileID) 206 } 207 208 resp, err := ethereumTransaction. 209 Execute(client) 210 if err != nil { 211 return TransactionResponse{}, err 212 } 213 214 _, err = resp.GetReceipt(client) 215 if err != nil { 216 return TransactionResponse{}, err 217 } 218 219 return resp, nil 220 }