decred.org/dcrdex@v1.0.5/client/asset/eth/cmd/getgas/main.go (about) 1 // This code is available on the terms of the project LICENSE.md file, 2 // also available online at https://blueoakcouncil.org/license/1.0.0. 3 4 package main 5 6 import ( 7 "context" 8 "flag" 9 "fmt" 10 "os" 11 "os/user" 12 "path/filepath" 13 "strings" 14 15 "decred.org/dcrdex/client/asset/eth" 16 "decred.org/dcrdex/client/asset/polygon" 17 "decred.org/dcrdex/dex" 18 dexeth "decred.org/dcrdex/dex/networks/eth" 19 dexpolygon "decred.org/dcrdex/dex/networks/polygon" 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/params" 22 ) 23 24 func main() { 25 if err := mainErr(); err != nil { 26 fmt.Fprint(os.Stderr, err, "\n") 27 os.Exit(1) 28 } 29 os.Exit(0) 30 } 31 32 func mainErr() error { 33 ctx, cancel := context.WithCancel(context.Background()) 34 defer cancel() 35 36 u, err := user.Current() 37 if err != nil { 38 return fmt.Errorf("could not get the current user: %w", err) 39 } 40 defaultCredentialsPath := filepath.Join(u.HomeDir, "dextest", "credentials.json") 41 42 var maxSwaps, contractVerI int 43 var chain, token, credentialsPath, returnAddr string 44 var useTestnet, useMainnet, useSimnet, trace, debug, readCreds, fundingReq bool 45 flag.BoolVar(&readCreds, "readcreds", false, "does not run gas estimates. read the credentials file and print the address") 46 flag.BoolVar(&fundingReq, "fundingrequired", false, "does not run gas estimates. calculate the funding required by the wallet to get estimates") 47 flag.StringVar(&returnAddr, "return", "", "does not run gas estimates. return ethereum funds to supplied address") 48 flag.BoolVar(&useMainnet, "mainnet", false, "use mainnet") 49 flag.BoolVar(&useTestnet, "testnet", false, "use testnet") 50 flag.BoolVar(&useSimnet, "simnet", false, "use simnet") 51 flag.BoolVar(&trace, "trace", false, "use simnet") 52 flag.BoolVar(&debug, "debug", false, "use simnet") 53 flag.IntVar(&maxSwaps, "n", 5, "max number of swaps per transaction. minimum is 2. test will run from 2 swap up to n swaps.") 54 flag.StringVar(&chain, "chain", "eth", "symbol of the base chain") 55 flag.StringVar(&token, "token", "", "symbol of the token. if token is not specified, will check gas for base chain") 56 flag.IntVar(&contractVerI, "ver", 0, "contract version") 57 flag.StringVar(&credentialsPath, "creds", defaultCredentialsPath, "path for JSON credentials file.") 58 flag.Parse() 59 60 if !useMainnet && !useTestnet && !useSimnet { 61 return fmt.Errorf("no network specified. add flag --mainnet, --testnet, or --simnet") 62 } 63 if (useMainnet && useTestnet) || (useMainnet && useSimnet) || (useTestnet && useSimnet) { 64 return fmt.Errorf("more than one network specified") 65 } 66 67 net := dex.Mainnet 68 if useSimnet { 69 net = dex.Simnet 70 dexeth.MaybeReadSimnetAddrs() 71 dexpolygon.MaybeReadSimnetAddrs() 72 } 73 if useTestnet { 74 net = dex.Testnet 75 } 76 77 if readCreds { 78 addr, providers, err := eth.GetGas.ReadCredentials(chain, credentialsPath, net) 79 if err != nil { 80 return err 81 } 82 fmt.Println("Credentials successfully parsed") 83 fmt.Println("Address:", addr) 84 fmt.Println("Providers:", strings.Join(providers, ", ")) 85 return nil 86 } 87 88 if maxSwaps < 2 { 89 return fmt.Errorf("n cannot be < 2") 90 } 91 92 if token == "" { 93 token = chain 94 } 95 96 // Allow specification of tokens without .[chain] suffix. 97 if chain != token && !strings.Contains(token, ".") { 98 token = token + "." + chain 99 } 100 101 assetID, found := dex.BipSymbolID(token) 102 if !found { 103 return fmt.Errorf("asset %s not known", token) 104 } 105 contractVer := uint32(contractVerI) 106 107 logLvl := dex.LevelInfo 108 if debug { 109 logLvl = dex.LevelDebug 110 } 111 if trace { 112 logLvl = dex.LevelTrace 113 } 114 115 log := dex.StdOutLogger("GG", logLvl) 116 117 walletParams := func( 118 gases map[uint32]*dexeth.Gases, 119 contracts map[uint32]map[dex.Network]common.Address, 120 tokens map[uint32]*dexeth.Token, 121 compatLookup func(net dex.Network) (c eth.CompatibilityData, err error), 122 chainCfg func(net dex.Network) (c *params.ChainConfig, err error), 123 bui *dex.UnitInfo, 124 ) (*eth.GetGasWalletParams, error) { 125 126 wParams := new(eth.GetGasWalletParams) 127 wParams.BaseUnitInfo = bui 128 if token != chain { 129 var exists bool 130 tkn, exists := tokens[assetID] 131 if !exists { 132 return nil, fmt.Errorf("specified token %s does not exist on base chain %s", token, chain) 133 } 134 wParams.Token = tkn 135 wParams.UnitInfo = &tkn.UnitInfo 136 netToken, exists := tkn.NetTokens[net] 137 if !exists { 138 return nil, fmt.Errorf("no %s token on %s network %s", tkn.Name, chain, net) 139 } 140 swapContract, exists := netToken.SwapContracts[contractVer] 141 if !exists { 142 return nil, fmt.Errorf("no verion %d contract for %s token on %s network %s", contractVer, tkn.Name, chain, net) 143 } 144 wParams.Gas = &swapContract.Gas 145 } else { 146 wParams.UnitInfo = bui 147 g, exists := gases[contractVer] 148 if !exists { 149 return nil, fmt.Errorf("no verion %d contract for %s network %s", contractVer, chain, net) 150 } 151 wParams.Gas = g 152 cs, exists := contracts[contractVer] 153 if !exists { 154 return nil, fmt.Errorf("no version %d base chain swap contract on %s", contractVer, chain) 155 } 156 wParams.ContractAddr, exists = cs[net] 157 if !exists { 158 return nil, fmt.Errorf("no version %d base chain swap contract on %s network %s", contractVer, chain, net) 159 } 160 } 161 wParams.ChainCfg, err = chainCfg(net) 162 if err != nil { 163 return nil, fmt.Errorf("error finding chain config: %v", err) 164 } 165 compat, err := compatLookup(net) 166 if err != nil { 167 return nil, fmt.Errorf("error finding api compatibility data: %v", err) 168 } 169 wParams.Compat = &compat 170 return wParams, nil 171 } 172 173 var wParams *eth.GetGasWalletParams 174 switch chain { 175 case "eth": 176 wParams, err = walletParams(dexeth.VersionedGases, dexeth.ContractAddresses, dexeth.Tokens, 177 eth.NetworkCompatibilityData, eth.ChainConfig, &dexeth.UnitInfo) 178 case "polygon": 179 wParams, err = walletParams(dexpolygon.VersionedGases, dexpolygon.ContractAddresses, dexpolygon.Tokens, 180 polygon.NetworkCompatibilityData, polygon.ChainConfig, &dexpolygon.UnitInfo) 181 default: 182 return fmt.Errorf("chain %s not known", chain) 183 } 184 if err != nil { 185 return fmt.Errorf("error generating wallet params: %w", err) 186 } 187 188 switch { 189 case fundingReq: 190 return eth.GetGas.EstimateFunding(ctx, net, assetID, contractVer, maxSwaps, credentialsPath, wParams, log) 191 case returnAddr != "": 192 return eth.GetGas.Return(ctx, assetID, credentialsPath, returnAddr, wParams, net, log) 193 default: 194 return eth.GetGas.Estimate(ctx, net, assetID, contractVer, maxSwaps, credentialsPath, wParams, log) 195 } 196 }