Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
mcdee committed Sep 29, 2017
0 parents commit 88644ed
Show file tree
Hide file tree
Showing 15 changed files with 1,190 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ethereal

# Vim
*.sw?
14 changes: 14 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Features
- transaction
- regas (txID)
- cancel (txID)
- transact (txID)
- ether
- balance (address)
- transfer (address, amount)
- token
- info (token)
- balance (token, address)
- transfer (token, address, address, amount)
- ens
- domainsale
29 changes: 29 additions & 0 deletions cmd/ether.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright © 2017 Weald Technology Trading
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"github.com/spf13/cobra"
)

// etherCmd represents the ether command
var etherCmd = &cobra.Command{
Use: "ether",
Short: "Manage Ether balances",
Long: `Obtain balances and transfer funds between addresses.`,
}

func init() {
RootCmd.AddCommand(etherCmd)
}
66 changes: 66 additions & 0 deletions cmd/etherbalance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright © 2017 Weald Technology Trading
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"context"
"fmt"
"math/big"
"os"

etherutils "github.com/orinocopay/go-etherutils"
"github.com/orinocopay/go-etherutils/cli"
"github.com/orinocopay/go-etherutils/ens"
"github.com/spf13/cobra"
)

// etherBalanceCmd represents the ether balance command
var etherBalanceCmd = &cobra.Command{
Use: "balance",
Short: "Obtain the balance for an address",
Long: `Obtain the Ether balance for an address. For example:
ethereal ether balance 0x5FfC014343cd971B7eb70732021E26C35B744cc4
In quiet mode this will return 0 if the balance is greater than 0, otherwise 1.`,
Run: func(cmd *cobra.Command, args []string) {
cli.Assert(args[0] != "", quiet, "Address is required")

address, err := ens.Resolve(client, args[0])
cli.ErrCheck(err, quiet, "Failed to obtain address")

// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
// defer cancel()

// TODO have a --pending flag?
// PendingStateReader ?
// balance, err := PendingBalanceAt(ctx, address)
balance, err := client.BalanceAt(context.Background(), address, nil)
cli.ErrCheck(err, quiet, "Failed to obtain balance")

if quiet {
if balance.Cmp(big.NewInt(0)) == 0 {
os.Exit(1)
} else {
os.Exit(0)
}
}

fmt.Printf("%s\n", etherutils.WeiToString(balance, true))
},
}

func init() {
etherCmd.AddCommand(etherBalanceCmd)
}
172 changes: 172 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Copyright © 2017 Weald Technology Trading
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"context"
"fmt"
"math/big"
"os"
"path/filepath"
"time"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
homedir "github.com/mitchellh/go-homedir"
etherutils "github.com/orinocopay/go-etherutils"
"github.com/orinocopay/go-etherutils/cli"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/wealdtech/go-domainsale/domainsalecontract"
)

var cfgFile string
var logFile string
var quiet bool
var connection string

var client *ethclient.Client
var chainID *big.Int
var referrer common.Address
var nonce int64

// Common variables
var passphrase string
var gasPriceStr string
var gasPrice *big.Int

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "ethereal",
Short: "Ethereum CLI",
Long: `Manage common Ethereum tasks from the command line.`,
PersistentPreRun: persistentPreRun,
}

func persistentPreRun(cmd *cobra.Command, args []string) {
if cmd.Name() == "help" {
// User just wants help
return
}

if cmd.Name() == "version" {
// User just wants the version
return
}

// Set default log file if no alternative is provided
if logFile == "" {
home, err := homedir.Dir()
cli.ErrCheck(err, quiet, "Failed to access home directory")
logFile = filepath.FromSlash(home + "/.ethereal.log")
}
f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755)
cli.ErrCheck(err, quiet, "Failed to open log file")
log.SetOutput(f)
log.SetFormatter(&log.JSONFormatter{})

// Create a connection to an Ethereum node
client, err = ethclient.Dial(connection)
cli.ErrCheck(err, quiet, "Failed to connect to Ethereum")
// Fetch the chain ID
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
chainID, err = client.NetworkID(ctx)
cli.ErrCheck(err, quiet, "Failed to obtain chain ID")

// Set up gas price
if gasPriceStr == "" {
gasPrice, err = etherutils.StringToWei("4 GWei")
cli.ErrCheck(err, quiet, "Invalid gas price")
} else {
gasPrice, err = etherutils.StringToWei(gasPriceStr)
cli.ErrCheck(err, quiet, "Invalid gas price")
}
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func init() {
cobra.OnInitialize(initConfig)

// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cmd.yaml)")
RootCmd.PersistentFlags().StringVarP(&logFile, "log", "l", "", "log activity to the named file (default $HOME/.ethereal.log)")
RootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "no output")
RootCmd.PersistentFlags().StringVarP(&connection, "connection", "c", "https://api.orinocopay.com:8546/", "path to the Ethereum connection")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}

// Search config in home directory with name ".cmd" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".cmd")
}

viper.AutomaticEnv() // read in environment variables that match

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}

//
// Helpers
//

// Add flags for commands that carry out transactions
func addTransactionFlags(cmd *cobra.Command, passphraseExplanation string) {
cmd.Flags().StringVarP(&passphrase, "passphrase", "p", "", passphraseExplanation)
cmd.Flags().StringVarP(&gasPriceStr, "gasprice", "g", "4 GWei", "Gas price for the transaction")
cmd.Flags().Int64VarP(&nonce, "nonce", "n", -1, "Nonce for the transaction; -1 is auto-select")
}

// Augment session information
func augmentSession(session *domainsalecontract.DomainSaleContractSession) {
session.TransactOpts.GasPrice = gasPrice
if nonce != -1 {
session.TransactOpts.Nonce = big.NewInt(nonce)
}
}

func obtainWalletAndAccount(address common.Address, passphrase string) (wallet accounts.Wallet, account *accounts.Account, err error) {
wallet, err = cli.ObtainWallet(chainID, address)
if err == nil {
account, err = cli.ObtainAccount(&wallet, &address, passphrase)
}
return wallet, account, err
}
63 changes: 63 additions & 0 deletions cmd/token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright © 2017 Weald Technology Trading
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/orinocopay/go-etherutils/ens"
"github.com/spf13/cobra"
"github.com/wealdtech/ethereal/util"
"github.com/wealdtech/ethereal/util/contracts"
)

var tokenStr string

// tokenCmd represents the token command
var tokenCmd = &cobra.Command{
Use: "token",
Short: "Manage tokens",
Long: `Obtain information, balances and transfer tokens between addresses.`,
}

var unknownAddress = common.HexToAddress("00")

// Obtain the token contract given a string
func tokenContract(input string) (contract *contracts.ERC20, err error) {
var addr common.Address
// See if this looks like a hex address
if strings.HasPrefix(input, "0x") || len(input) == 64 {
addr = common.HexToAddress(input)
}
if addr == unknownAddress {
// Guess 2 - try {input}.thetoken.eth
addr, err = ens.Resolve(client, input+".thetoken.eth")
if err != nil {
// Give up
err = fmt.Errorf("Unknown token %s", input)
}
}
contract, err = util.ERC20Contract(client, addr)
return
}

func init() {
RootCmd.AddCommand(tokenCmd)
}

func tokenFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&tokenStr, "token", "t", "", "Name or address of the token")
}
Loading

0 comments on commit 88644ed

Please sign in to comment.