-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add offline create wallet flow, fix transaction submit expiration bug (…
…#48)
- Loading branch information
Showing
5 changed files
with
322 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,186 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/hex" | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"log" | ||
"os" | ||
|
||
"github.com/brave-intl/bat-go/utils/altcurrency" | ||
"github.com/brave-intl/bat-go/utils/formatters" | ||
"github.com/brave-intl/bat-go/utils/httpsignature" | ||
"github.com/brave-intl/bat-go/utils/vaultsigner" | ||
"github.com/brave-intl/bat-go/wallet" | ||
"github.com/brave-intl/bat-go/wallet/provider/uphold" | ||
"github.com/hashicorp/vault/api" | ||
log "github.com/sirupsen/logrus" | ||
"golang.org/x/crypto/ed25519" | ||
) | ||
|
||
var flags = flag.NewFlagSet("", flag.ExitOnError) | ||
var verbose = flags.Bool("v", false, "verbose output") | ||
var offline = flags.Bool("offline", false, "operate in multi-step offline mode") | ||
|
||
// State contains the current state of the registration | ||
type State struct { | ||
WalletInfo wallet.Info `json:"walletInfo"` | ||
Registration string `json:"registration"` | ||
} | ||
|
||
func main() { | ||
log.SetFlags(0) | ||
log.SetFormatter(&formatters.CliFormatter{}) | ||
|
||
flag.Usage = func() { | ||
flags.Usage = func() { | ||
log.Printf("Create a new wallet backed by vault.\n\n") | ||
log.Printf("Usage:\n\n") | ||
log.Printf(" %s WALLET_NAME\n\n", os.Args[0]) | ||
log.Printf(" If a vault keypair exists with name WALLET_NAME, it will be used.\n") | ||
log.Printf(" Otherwise a new vault keypair with that name will be generated.\n\n") | ||
flags.PrintDefaults() | ||
} | ||
err := flags.Parse(os.Args[1:]) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
if *verbose { | ||
log.SetLevel(log.DebugLevel) | ||
} | ||
flag.Parse() | ||
|
||
args := flag.Args() | ||
args := flags.Args() | ||
if len(args) != 1 { | ||
log.Printf("ERROR: Must pass a single argument to name generated wallet / keypair\n\n") | ||
flag.Usage() | ||
flags.Usage() | ||
os.Exit(1) | ||
} | ||
|
||
name := args[0] | ||
logFile := name + "-registration.json" | ||
|
||
var state State | ||
var enc *json.Encoder | ||
|
||
var info wallet.Info | ||
info.Provider = "uphold" | ||
info.ProviderID = "" | ||
{ | ||
tmp := altcurrency.BAT | ||
info.AltCurrency = &tmp | ||
if *offline { | ||
f, err := os.OpenFile(logFile, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
dec := json.NewDecoder(f) | ||
|
||
for dec.More() { | ||
err := dec.Decode(&state) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
} | ||
|
||
enc = json.NewEncoder(f) | ||
} | ||
|
||
client, err := vaultsigner.Connect() | ||
if err != nil { | ||
log.Fatalln(err) | ||
if len(state.WalletInfo.PublicKey) == 0 || len(state.Registration) == 0 { | ||
var info wallet.Info | ||
info.Provider = "uphold" | ||
info.ProviderID = "" | ||
{ | ||
tmp := altcurrency.BAT | ||
info.AltCurrency = &tmp | ||
} | ||
state.WalletInfo = info | ||
|
||
client, err := vaultsigner.Connect() | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
signer, err := vaultsigner.New(client, name) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
fmt.Printf("Keypair with public key: %s\n", signer) | ||
|
||
state.WalletInfo.PublicKey = signer.String() | ||
|
||
wallet := &uphold.Wallet{Info: state.WalletInfo, PrivKey: signer, PubKey: signer} | ||
|
||
reg, err := wallet.PrepareRegistration(name) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
state.Registration = reg | ||
|
||
if *offline { | ||
err = enc.Encode(state) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
fmt.Printf("Success, signed registration for wallet \"%s\"\n", name) | ||
fmt.Printf("Please copy %s to the online machine and re-run.\n", logFile) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
signer, err := vaultsigner.New(client, name) | ||
if len(state.WalletInfo.ProviderID) == 0 { | ||
var publicKey httpsignature.Ed25519PubKey | ||
publicKey, err := hex.DecodeString(state.WalletInfo.PublicKey) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
wallet := uphold.Wallet{Info: state.WalletInfo, PrivKey: ed25519.PrivateKey{}, PubKey: publicKey} | ||
|
||
err = wallet.SubmitRegistration(state.Registration) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
fmt.Printf("Success, registered new keypair and wallet \"%s\"\n", name) | ||
fmt.Printf("Uphold card ID %s\n", wallet.Info.ProviderID) | ||
state.WalletInfo.ProviderID = wallet.Info.ProviderID | ||
|
||
depositAddr, err := wallet.CreateCardAddress("ethereum") | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
fmt.Printf("ETH deposit addr: %s\n", depositAddr) | ||
|
||
if *offline { | ||
err = enc.Encode(state) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
fmt.Printf("Please copy %s to the offline machine and re-run.\n", logFile) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
client, err := vaultsigner.Connect() | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
fmt.Printf("Generated keypair with public key: %s\n", signer) | ||
|
||
wallet := &uphold.Wallet{Info: info, PrivKey: signer, PubKey: signer} | ||
err = wallet.Register(name) | ||
mounts, err := client.Sys().ListMounts() | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
if _, ok := mounts["wallets/"]; !ok { | ||
// Mount kv secret backend if not already mounted | ||
if err = client.Sys().Mount("wallets", &api.MountInput{ | ||
Type: "kv", | ||
}); err != nil { | ||
log.Fatalln(err) | ||
} | ||
} | ||
|
||
fmt.Printf("Success, registered new keypair and wallet \"%s\"\n", name) | ||
fmt.Printf("Uphold card ID %s", wallet.Info.ProviderID) | ||
_, err = client.Logical().Write("wallets/"+name, map[string]interface{}{ | ||
"providerId": wallet.Info.ProviderID, | ||
"providerId": state.WalletInfo.ProviderID, | ||
}) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
fmt.Printf("Wallet setup complete!\n") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.