github.com/0chain/gosdk@v1.17.11/wasmsdk/bridge.go (about) 1 package main 2 3 import ( 4 "context" 5 "encoding/base64" 6 "encoding/json" 7 "path" 8 "strconv" 9 "time" 10 11 "github.com/0chain/gosdk/zcnbridge" 12 "github.com/0chain/gosdk/zcnbridge/errors" 13 "github.com/0chain/gosdk/zcnbridge/log" 14 "github.com/0chain/gosdk/zcnbridge/transaction" 15 "github.com/0chain/gosdk/zcnbridge/wallet" 16 "github.com/0chain/gosdk/zcncore" 17 "github.com/ethereum/go-ethereum/ethclient" 18 ) 19 20 var bridge *zcnbridge.BridgeClient 21 22 // initBridge initializes the bridge client 23 // - ethereumAddress: ethereum address of the wallet owner 24 // - bridgeAddress: address of the bridge contract on the Ethereum network 25 // - authorizersAddress: address of the authorizers contract on the Ethereum network 26 // - tokenAddress: address of the token contract on the Ethereum network 27 // - ethereumNodeURL: URL of the Ethereum node 28 // - gasLimit: gas limit for the transactions 29 // - value: value to be sent with the transaction (unused) 30 // - consensusThreshold: consensus threshold for the transactions 31 func initBridge( 32 ethereumAddress string, 33 bridgeAddress string, 34 authorizersAddress string, 35 tokenAddress string, 36 ethereumNodeURL string, 37 gasLimit uint64, 38 value int64, 39 consensusThreshold float64) error { 40 if len(zcncore.GetWalletRaw().ClientID) == 0 { 41 return errors.New("wallet_error", "wallet is not set") 42 } 43 44 ethereumClient, err := ethclient.Dial(ethereumNodeURL) 45 if err != nil { 46 return errors.New("wallet_error", err.Error()) 47 } 48 49 transactionProvider := transaction.NewTransactionProvider() 50 51 keyStore := zcnbridge.NewKeyStore( 52 path.Join(".", zcnbridge.EthereumWalletStorageDir)) 53 54 bridge = zcnbridge.NewBridgeClient( 55 bridgeAddress, 56 tokenAddress, 57 authorizersAddress, 58 "", 59 ethereumAddress, 60 ethereumNodeURL, 61 "", 62 gasLimit, 63 consensusThreshold, 64 ethereumClient, 65 transactionProvider, 66 keyStore, 67 ) 68 69 return nil 70 } 71 72 // burnZCN Burns ZCN tokens and returns a hash of the burn transaction 73 // - amount: amount of ZCN tokens to burn 74 // - txnfee: transaction fee 75 func burnZCN(amount, txnfee uint64) string { //nolint 76 if bridge == nil { 77 return errors.New("burnZCN", "bridge is not initialized").Error() 78 } 79 80 tx, err := bridge.BurnZCN(context.Background(), amount, txnfee) 81 if err != nil { 82 return errors.Wrap("burnZCN", "failed to burn ZCN tokens", err).Error() 83 } 84 85 return tx.GetHash() 86 } 87 88 // mintZCN Mints ZCN tokens and returns a hash of the mint transaction 89 // - burnTrxHash: hash of the burn transaction 90 // - timeout: timeout in seconds 91 func mintZCN(burnTrxHash string, timeout int) string { //nolint 92 mintPayload, err := bridge.QueryZChainMintPayload(burnTrxHash) 93 if err != nil { 94 return errors.Wrap("mintZCN", "failed to QueryZChainMintPayload", err).Error() 95 } 96 97 c, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) 98 defer cancel() 99 100 hash, err := bridge.MintZCN(c, mintPayload) 101 if err != nil { 102 return errors.Wrap("mintZCN", "failed to MintZCN for txn "+hash, err).Error() 103 } 104 105 return hash 106 } 107 108 // getMintWZCNPayload returns the mint payload for the given burn transaction hash 109 // - burnTrxHash: hash of the burn transaction 110 func getMintWZCNPayload(burnTrxHash string) string { 111 mintPayload, err := bridge.QueryEthereumMintPayload(burnTrxHash) 112 if err != nil { 113 return errors.Wrap("getMintWZCNPayload", "failed to query ethereum mint payload", err).Error() 114 } 115 var result []byte 116 result, err = json.Marshal(mintPayload) 117 if err != nil { 118 return errors.Wrap("getMintWZCNPayload", "failed to query ethereum mint payload", err).Error() 119 } 120 121 return string(result) 122 } 123 124 // getNotProcessedWZCNBurnEvents returns all not processed WZCN burn events from the Ethereum network 125 func getNotProcessedWZCNBurnEvents() string { 126 var mintNonce int64 127 cb := wallet.NewZCNStatus(&mintNonce) 128 129 cb.Begin() 130 131 if err := zcncore.GetMintNonce(cb); err != nil { 132 return errors.Wrap("getNotProcessedWZCNBurnEvents", "failed to retreive last ZCN processed mint nonce", err).Error() 133 } 134 135 if err := cb.Wait(); err != nil { 136 return errors.Wrap("getNotProcessedWZCNBurnEvents", "failed to retreive last ZCN processed mint nonce", err).Error() 137 } 138 139 if !cb.Success { 140 return errors.New("getNotProcessedWZCNBurnEvents", "failed to retreive last ZCN processed mint nonce").Error() 141 } 142 143 log.Logger.Debug("MintNonce = " + strconv.Itoa(int(mintNonce))) 144 burnEvents, err := bridge.QueryEthereumBurnEvents(strconv.Itoa(int(mintNonce))) 145 if err != nil { 146 return errors.Wrap("getNotProcessedWZCNBurnEvents", "failed to retrieve WZCN burn events", err).Error() 147 } 148 149 var result []byte 150 result, err = json.Marshal(burnEvents) 151 if err != nil { 152 return errors.Wrap("getNotProcessedWZCNBurnEvents", "failed to marshal WZCN burn events", err).Error() 153 } 154 155 return string(result) 156 } 157 158 // getNotProcessedZCNBurnTickets Returns all not processed ZCN burn tickets burned for a certain ethereum address 159 func getNotProcessedZCNBurnTickets() string { 160 userNonce, err := bridge.GetUserNonceMinted(context.Background(), bridge.EthereumAddress) 161 if err != nil { 162 return errors.Wrap("getNotProcessedZCNBurnTickets", "failed to retreive user nonce", err).Error() 163 } 164 165 var burnTickets []zcncore.BurnTicket 166 cb := wallet.NewZCNStatus(&burnTickets) 167 cb.Begin() 168 169 err = zcncore.GetNotProcessedZCNBurnTickets(bridge.EthereumAddress, userNonce.String(), cb) 170 if err != nil { 171 return errors.Wrap("getNotProcessedZCNBurnTickets", "failed to retreive ZCN burn tickets", err).Error() 172 } 173 174 if err := cb.Wait(); err != nil { 175 return errors.Wrap("getNotProcessedZCNBurnTickets", "failed to retreive ZCN burn tickets", err).Error() 176 } 177 178 if !cb.Success { 179 return errors.New("getNotProcessedZCNBurnTickets", "failed to retreive ZCN burn tickets").Error() 180 } 181 182 var result []byte 183 result, err = json.Marshal(burnTickets) 184 if err != nil { 185 return errors.Wrap("getNotProcessedZCNBurnTickets", "failed to marshal ZCN burn tickets", err).Error() 186 } 187 188 return string(result) 189 } 190 191 // estimateBurnWZCNGasAmount performs gas amount estimation for the given burn wzcn transaction. 192 // - from: address of the sender 193 // - to: address of the receiver 194 // - amountTokens: amount of tokens to burn (as a string) 195 func estimateBurnWZCNGasAmount(from, to, amountTokens string) string { // nolint:golint,unused 196 estimateBurnWZCNGasAmountResponse, err := bridge.EstimateBurnWZCNGasAmount( 197 context.Background(), from, to, amountTokens) 198 if err != nil { 199 return errors.Wrap("estimateBurnWZCNGasAmount", "failed to estimate gas amount", err).Error() 200 } 201 202 var result []byte 203 result, err = json.Marshal(estimateBurnWZCNGasAmountResponse) 204 if err != nil { 205 return errors.Wrap("estimateBurnWZCNGasAmount", "failed to marshal gas amount estimation result", err).Error() 206 } 207 208 return string(result) 209 } 210 211 // estimateMintWZCNGasAmount performs gas amount estimation for the given mint wzcn transaction. 212 // - from: address of the sender 213 // - to: address of the receiver 214 // - zcnTransaction: hash of the ZCN transaction 215 // - amountToken: amount of tokens to mint (as a string) 216 // - nonce: nonce of the transaction 217 // - signaturesRaw: encoded format (base-64) of the burn signatures received from the authorizers. 218 func estimateMintWZCNGasAmount(from, to, zcnTransaction, amountToken string, nonce int64, signaturesRaw []string) string { // nolint:golint,unused 219 var signaturesBytes [][]byte 220 221 var ( 222 signatureBytes []byte 223 err error 224 ) 225 226 for _, signature := range signaturesRaw { 227 signatureBytes, err = base64.StdEncoding.DecodeString(signature) 228 if err != nil { 229 return errors.Wrap("estimateMintWZCNGasAmount", "failed to convert raw signature into bytes", err).Error() 230 } 231 232 signaturesBytes = append(signaturesBytes, signatureBytes) 233 } 234 235 estimateMintWZCNGasAmountResponse, err := bridge.EstimateMintWZCNGasAmount( 236 context.Background(), from, to, zcnTransaction, amountToken, nonce, signaturesBytes) 237 if err != nil { 238 return errors.Wrap("estimateMintWZCNGasAmount", "failed to estimate gas amount", err).Error() 239 } 240 241 var result []byte 242 result, err = json.Marshal(estimateMintWZCNGasAmountResponse) 243 if err != nil { 244 return errors.Wrap("estimateMintWZCNGasAmount", "failed to marshal gas amount estimation result", err).Error() 245 } 246 247 return string(result) 248 } 249 250 // estimateGasPrice performs gas estimation for the given transaction using Alchemy enhanced API returning 251 // approximate final gas fee. 252 func estimateGasPrice() string { // nolint:golint,unused 253 estimateGasPriceResponse, err := bridge.EstimateGasPrice(context.Background()) 254 if err != nil { 255 return errors.Wrap("estimateGasPrice", "failed to estimate gas price", err).Error() 256 } 257 258 var result []byte 259 result, err = json.Marshal(estimateGasPriceResponse) 260 if err != nil { 261 return errors.Wrap("estimateGasPrice", "failed to marshal gas price estimation result", err).Error() 262 } 263 264 return string(result) 265 }