diff --git a/api/client.go b/api/client.go
index 3f4623c5af5179a02fc8ce368306c2f54974d0b4..3c39f1194060b4d3b18c280d7cd21766715132a8 100644
--- a/api/client.go
+++ b/api/client.go
@@ -215,8 +215,7 @@ func NewProtoClient_Unsafe(ndfJSON, storageDir string, password,
 }
 
 // Login initializes a client object from existing storage.
-func Login(storageDir string, password []byte,
-	authCallbacks auth.Callbacks, parameters Params) (*Client, error) {
+func Login(storageDir string, password []byte, parameters Params) (*Client, error) {
 	jww.INFO.Printf("Login()")
 
 	c, err := OpenClient(storageDir, password, parameters)
diff --git a/bindings/client.go b/bindings/client.go
index a160886728f0d7f0975be56956cca85171825883..e9a60f713ba0800cceefb7ed9bd4d19fabc9f7cd 100644
--- a/bindings/client.go
+++ b/bindings/client.go
@@ -1,54 +1,30 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                          //
-//                                                                           //
-// Use of this source code is governed by a license that can be found in the //
-// LICENSE file                                                              //
-///////////////////////////////////////////////////////////////////////////////
-
 package bindings
 
 import (
-	"bytes"
-	"encoding/csv"
-	"encoding/json"
-	"errors"
 	"fmt"
-	"gitlab.com/elixxir/client/cmix"
-	"gitlab.com/elixxir/client/single/old"
-	"runtime/pprof"
-	"strings"
-	"sync"
-	"time"
-
+	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/api"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/interfaces/params"
-	"gitlab.com/elixxir/comms/mixmessages"
-	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/primitives/states"
-	"gitlab.com/xx_network/primitives/id"
-	"gitlab.com/xx_network/primitives/netTime"
-	"google.golang.org/grpc/grpclog"
 )
 
-var extantClient bool = false
-var loginMux sync.Mutex
-
-var clientSingleton *Client
-
 // sets the log level
 func init() {
 	jww.SetLogThreshold(jww.LevelInfo)
 	jww.SetStdoutThreshold(jww.LevelInfo)
 }
 
-// BindingsClient wraps the api.Client, implementing additional functions
+//client tracker singleton, used to track clients so they can be referenced by
+//id back over the bindings
+var clientTrackerSingleton = &clientTracker{
+	clients: make(map[int]*Client),
+	count:   0,
+}
+
+// Client BindingsClient wraps the api.Client, implementing additional functions
 // to support the gomobile Client interface
 type Client struct {
-	api       api.Client
-	single    *old.Manager
-	singleMux sync.Mutex
+	api api.Client
+	id  int
 }
 
 // NewClient creates client storage, generates keys, connects, and registers
@@ -65,51 +41,6 @@ func NewClient(network, storageDir string, password []byte, regCode string) erro
 	return nil
 }
 
-// NewPrecannedClient creates an insecure user with predetermined keys with nodes
-// It creates client storage, generates keys, connects, and registers
-// with the network. Note that this does not register a username/identity, but
-// merely creates a new cryptographic identity for adding such information
-// at a later date.
-//
-// Users of this function should delete the storage directory on error.
-func NewPrecannedClient(precannedID int, network, storageDir string, password []byte) error {
-	if precannedID < 0 {
-		return errors.New("Cannot create precanned client with negative ID")
-	}
-
-	if err := api.NewPrecannedClient(uint(precannedID), network, storageDir, password); err != nil {
-		return errors.New(fmt.Sprintf("Failed to create new precanned "+
-			"client: %+v", err))
-	}
-	return nil
-}
-
-type BackupReport struct {
-	RestoredContacts []*id.ID
-	Params           string
-}
-
-// NewClientFromBackup constructs a new Client from an encrypted backup. The backup
-// is decrypted using the backupPassphrase. On success a successful client creation,
-// the function will return a JSON encoded list of the E2E partners
-// contained in the backup and a json-encoded string of the parameters stored in the backup
-func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword,
-	backupPassphrase, backupFileContents []byte) ([]byte, error) {
-	backupPartnerIds, jsonParams, err := api.NewClientFromBackup(ndfJSON, storageDir,
-		sessionPassword, backupPassphrase, backupFileContents)
-	if err != nil {
-		return nil, errors.New(fmt.Sprintf("Failed to create new "+
-			"client from backup: %+v", err))
-	}
-
-	report := BackupReport{
-		RestoredContacts: backupPartnerIds,
-		Params:           jsonParams,
-	}
-
-	return json.Marshal(report)
-}
-
 // Login will load an existing client from the storageDir
 // using the password. This will fail if the client doesn't exist or
 // the password is incorrect.
@@ -117,502 +48,20 @@ func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword,
 // memory and stored as securely as possible using the memguard library.
 // Login does not block on network connection, and instead loads and
 // starts subprocesses to perform network operations.
-func Login(storageDir string, password []byte, parameters string) (*Client, error) {
-	loginMux.Lock()
-	defer loginMux.Unlock()
+// TODO: add in custom parameters instead of the default
+func Login(storageDir string, password []byte) (*Client, error) {
 
-	if extantClient {
-		return nil, errors.New("cannot login when another session " +
-			"already exists")
-	}
-	// check if a client is already logged in, refuse to login if one is
-	p, err := params.GetNetworkParameters(parameters)
+	client, err := api.Login(storageDir, password, api.GetDefaultParams())
 	if err != nil {
 		return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err))
 	}
 
-	client, err := api.Login(storageDir, password, p)
-	if err != nil {
-		return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err))
-	}
-	extantClient = true
-	clientSingleton := &Client{api: *client}
-
-	return clientSingleton, nil
-}
-
-// returns a previously created client. IF be used if the garbage collector
-// removes the client instance on the app side.  Is NOT thread safe relative to
-// login, newClient, or newPrecannedClient
-func GetClientSingleton() *Client {
-	return clientSingleton
-}
-
-// sets level of logging. All logs the set level and above will be displayed
-// options are:
-//	TRACE		- 0
-//	DEBUG		- 1
-//	INFO 		- 2
-//	WARN		- 3
-//	ERROR		- 4
-//	CRITICAL	- 5
-//	FATAL		- 6
-// The default state without updates is: INFO
-func LogLevel(level int) error {
-	if level < 0 || level > 6 {
-		return errors.New(fmt.Sprintf("log level is not valid: log level: %d", level))
-	}
-
-	threshold := jww.Threshold(level)
-	jww.SetLogThreshold(threshold)
-	jww.SetStdoutThreshold(threshold)
-
-	switch threshold {
-	case jww.LevelTrace:
-		fallthrough
-	case jww.LevelDebug:
-		fallthrough
-	case jww.LevelInfo:
-		jww.INFO.Printf("Log level set to: %s", threshold)
-	case jww.LevelWarn:
-		jww.WARN.Printf("Log level set to: %s", threshold)
-	case jww.LevelError:
-		jww.ERROR.Printf("Log level set to: %s", threshold)
-	case jww.LevelCritical:
-		jww.CRITICAL.Printf("Log level set to: %s", threshold)
-	case jww.LevelFatal:
-		jww.FATAL.Printf("Log level set to: %s", threshold)
-	}
-
-	return nil
-}
-
-//RegisterLogWriter registers a callback on which logs are written.
-func RegisterLogWriter(writer LogWriter) {
-	jww.SetLogOutput(&writerAdapter{lw: writer})
-}
-
-// EnableGrpcLogs sets GRPC trace logging
-func EnableGrpcLogs(writer LogWriter) {
-	logger := &writerAdapter{lw: writer}
-	grpclog.SetLoggerV2(grpclog.NewLoggerV2WithVerbosity(
-		logger, logger, logger, 99))
-}
-
-//Unmarshals a marshaled contact object, returns an error if it fails
-func UnmarshalContact(b []byte) (*Contact, error) {
-	c, err := contact.Unmarshal(b)
-	if err != nil {
-		return nil, errors.New(fmt.Sprintf("Failed to Unmarshal "+
-			"Contact: %+v", err))
-	}
-	return &Contact{c: &c}, nil
-}
-
-//Unmarshals a marshaled send report object, returns an error if it fails
-func UnmarshalSendReport(b []byte) (*SendReport, error) {
-	sr := &SendReport{}
-	return sr, sr.Unmarshal(b)
-}
-
-// StartNetworkFollower kicks off the tracking of the network. It starts
-// long running network client threads and returns an object for checking
-// state and stopping those threads.
-// Call this when returning from sleep and close when going back to
-// sleep.
-// These threads may become a significant drain on battery when offline, ensure
-// they are stopped if there is no internet access
-// Threads Started:
-//   - Network Follower (/network/follow.go)
-//   	tracks the network events and hands them off to workers for handling
-//   - Historical Round Retrieval (/network/rounds/historical.go)
-//		Retrieves data about rounds which are too old to be stored by the client
-//	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
-//		Requests all messages in a given round from the gateway of the last nodes
-//	 - Message Handling Worker Group (/network/message/handle.go)
-//		Decrypts and partitions messages when signals via the Switchboard
-//	 - health Tracker (/network/health)
-//		Via the network instance tracks the state of the network
-//	 - Garbled Messages (/network/message/garbled.go)
-//		Can be signaled to check all recent messages which could be be decoded
-//		Uses a message store on disk for persistence
-//	 - Critical Messages (/network/message/critical.go)
-//		Ensures all protocol layer mandatory messages are sent
-//		Uses a message store on disk for persistence
-//	 - KeyExchange Trigger (/keyExchange/trigger.go)
-//		Responds to sent rekeys and executes them
-//   - KeyExchange Confirm (/keyExchange/confirm.go)
-//		Responds to confirmations of successful rekey operations
-func (c *Client) StartNetworkFollower(timeoutMS int) error {
-	timeout := time.Duration(timeoutMS) * time.Millisecond
-	return c.api.StartNetworkFollower(timeout)
-}
-
-// RegisterClientErrorCallback registers the callback to handle errors from the
-// long running threads controlled by StartNetworkFollower and StopNetworkFollower
-func (c *Client) RegisterClientErrorCallback(clientError ClientError) {
-	errChan := c.api.GetErrorsChannel()
-	go func() {
-		for report := range errChan {
-			go clientError.Report(report.Source, report.Message, report.Trace)
-		}
-	}()
-}
-
-// StopNetworkFollower stops the network follower if it is running.
-// It returns errors if the Follower is in the wrong status to stop or if it
-// fails to stop it.
-// if the network follower is running and this fails, the client object will
-// most likely be in an unrecoverable state and need to be trashed.
-func (c *Client) StopNetworkFollower() error {
-	if err := c.api.StopNetworkFollower(); err != nil {
-		return errors.New(fmt.Sprintf("Failed to stop the "+
-			"network follower: %+v", err))
-	}
-	return nil
-}
-
-// WaitForNewtwork will block until either the network is healthy or the
-// passed timeout. It will return true if the network is healthy
-func (c *Client) WaitForNetwork(timeoutMS int) bool {
-	start := netTime.Now()
-	timeout := time.Duration(timeoutMS) * time.Millisecond
-	for netTime.Since(start) < timeout {
-		if c.api.GetHealth().IsHealthy() {
-			return true
-		}
-		time.Sleep(250 * time.Millisecond)
-	}
-	return false
-}
-
-// Gets the state of the network follower. Returns:
-// Stopped 	- 0
-// Starting - 1000
-// Running	- 2000
-// Stopping	- 3000
-func (c *Client) NetworkFollowerStatus() int {
-	return int(c.api.NetworkFollowerStatus())
-}
-
-// HasRunningProcessies checks if any background threads are running.
-// returns true if none are running. This is meant to be
-// used when NetworkFollowerStatus() returns Stopping.
-// Due to the handling of comms on iOS, where the OS can
-// block indefiently, it may not enter the stopped
-// state apropreatly. This can be used instead.
-func (c *Client) HasRunningProcessies() bool {
-	return c.api.HasRunningProcessies()
+	return clientTrackerSingleton.make(client), nil
 }
 
-// returns true if the network is read to be in a healthy state where
-// messages can be sent
-func (c *Client) IsNetworkHealthy() bool {
-	return c.api.GetHealth().IsHealthy()
+func (c *Client) GetID() int {
+	return c.id
 }
 
-// RegisterNetworkHealthCB registers the network health callback to be called
-// any time the network health changes. Returns a unique ID that can be used to
-// unregister the network health callback.
-func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) int64 {
-	return int64(c.api.GetHealth().AddFunc(nhc.Callback))
-}
-
-func (c *Client) UnregisterNetworkHealthCB(funcID int64) {
-	c.api.GetHealth().RemoveFunc(uint64(funcID))
-}
-
-// RegisterListener records and installs a listener for messages
-// matching specific uid, msgType, and/or username
-// Returns a ListenerUnregister interface which can be
-//
-// to register for any userID, pass in an id with length 0 or an id with
-// all zeroes
-//
-// to register for any message type, pass in a message type of 0
-//
-// Message Types can be found in client/interfaces/message/type.go
-// Make sure to not conflict with ANY default message types
-func (c *Client) RegisterListener(uid []byte, msgType int,
-	listener Listener) (*Unregister, error) {
-	jww.INFO.Printf("RegisterListener(%v, %d)", uid,
-		msgType)
-
-	name := listener.Name()
 
-	var u *id.ID
-	if len(uid) == 0 {
-		u = &id.ID{}
-	} else {
-		var err error
-		u, err = id.Unmarshal(uid)
-		if err != nil {
-			return nil, errors.New(fmt.Sprintf("Failed to "+
-				"ResgisterListener: %+v", err))
-		}
-	}
-
-	mt := message.Type(msgType)
-
-	f := func(item message.Receive) {
-		listener.Hear(&Message{r: item})
-	}
-
-	lid := c.api.GetSwitchboard().RegisterFunc(name, u, mt, f)
-
-	return newListenerUnregister(lid, c.api.GetSwitchboard()), nil
-}
-
-// RegisterRoundEventsHandler registers a callback interface for round
-// events.
-// The rid is the round the event attaches to
-// The timeoutMS is the number of milliseconds until the event fails, and the
-// validStates are a list of states (one per byte) on which the event gets
-// triggered
-// States:
-//  0x00 - PENDING (Never seen by client)
-//  0x01 - PRECOMPUTING
-//  0x02 - STANDBY
-//  0x03 - QUEUED
-//  0x04 - REALTIME
-//  0x05 - COMPLETED
-//  0x06 - FAILED
-// These states are defined in elixxir/primitives/states/state.go
-func (c *Client) RegisterRoundEventsHandler(rid int, cb RoundEventCallback,
-	timeoutMS int, il *IntList) *Unregister {
-
-	rcb := func(ri *mixmessages.RoundInfo, timedOut bool) {
-		cb.EventCallback(int(ri.ID), int(ri.State), timedOut)
-	}
 
-	timeout := time.Duration(timeoutMS) * time.Millisecond
-
-	vStates := make([]states.Round, len(il.lst))
-	for i, s := range il.lst {
-		vStates[i] = states.Round(s)
-	}
-
-	roundID := id.Round(rid)
-
-	ec := c.api.GetRoundEvents().AddRoundEvent(roundID, rcb, timeout)
-
-	return newRoundUnregister(roundID, ec, c.api.GetRoundEvents())
-}
-
-// WaitForRoundCompletion allows the caller to get notified if a round
-// has completed (or failed). Under the hood, this uses an API which uses the internal
-// round data, network historical round lookup, and waiting on network events
-// to determine what has (or will) occur.
-//
-// The callbacks will return at timeoutMS if no state update occurs
-func (c *Client) WaitForRoundCompletion(roundID int,
-	rec RoundCompletionCallback, timeoutMS int) error {
-
-	f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundLookupStatus) {
-		rec.EventCallback(roundID, allRoundsSucceeded, timedOut)
-	}
-
-	timeout := time.Duration(timeoutMS) * time.Millisecond
-
-	return c.api.GetRoundResults([]id.Round{id.Round(roundID)}, timeout, f)
-}
-
-// WaitForMessageDelivery allows the caller to get notified if the rounds a
-// message was sent in successfully completed. Under the hood, this uses an API
-// which uses the internal round data, network historical round lookup, and
-// waiting on network events to determine what has (or will) occur.
-//
-// The callbacks will return at timeoutMS if no state update occurs
-//
-// This function takes the marshaled send report to ensure a memory leak does
-// not occur as a result of both sides of the bindings holding a reference to
-// the same pointer.
-func (c *Client) WaitForMessageDelivery(marshaledSendReport []byte,
-	mdc MessageDeliveryCallback, timeoutMS int) error {
-	jww.INFO.Printf("WaitForMessageDelivery(%v, _, %v)",
-		marshaledSendReport, timeoutMS)
-	sr, err := UnmarshalSendReport(marshaledSendReport)
-	if err != nil {
-		return errors.New(fmt.Sprintf("Failed to "+
-			"WaitForMessageDelivery callback due to bad Send Report: %+v", err))
-	}
-
-	if sr == nil || sr.rl == nil || len(sr.rl.list) == 0 {
-		return errors.New(fmt.Sprintf("Failed to "+
-			"WaitForMessageDelivery callback due to invalid Send Report "+
-			"unmarshal: %s", string(marshaledSendReport)))
-	}
-
-	f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundLookupStatus) {
-		results := make([]byte, len(sr.rl.list))
-		jww.INFO.Printf("Processing WaitForMessageDelivery report "+
-			"for %v, success: %v, timedout: %v", sr.mid, allRoundsSucceeded,
-			timedOut)
-		for i, r := range sr.rl.list {
-			if result, exists := rounds[r]; exists {
-				results[i] = byte(result)
-			}
-		}
-
-		mdc.EventCallback(sr.mid.Marshal(), allRoundsSucceeded, timedOut, results)
-	}
-
-	timeout := time.Duration(timeoutMS) * time.Millisecond
-
-	err = c.api.GetRoundResults(sr.rl.list, timeout, f)
-
-	return err
-}
-
-// Returns a user object from which all information about the current user
-// can be gleaned
-func (c *Client) GetUser() *User {
-	u := c.api.GetUser()
-	return &User{u: &u}
-}
-
-// GetNodeRegistrationStatus returns a struct with the number of nodes the
-// client is registered with and the number total.
-func (c *Client) GetNodeRegistrationStatus() (*NodeRegistrationsStatus, error) {
-	registered, total, err := c.api.GetNodeRegistrationStatus()
-
-	return &NodeRegistrationsStatus{registered, total}, err
-}
-
-// DeleteRequest will delete a request, agnostic of request type
-// for the given partner ID. If no request exists for this
-// partner ID an error will be returned.
-func (c *Client) DeleteRequest(requesterUserId []byte) error {
-	requesterId, err := id.Unmarshal(requesterUserId)
-	if err != nil {
-		return err
-	}
-
-	jww.DEBUG.Printf("Deleting request for partner ID: %s", requesterId)
-	return c.api.DeleteRequest(requesterId)
-}
-
-// DeleteAllRequests clears all requests from Client's auth storage.
-func (c *Client) DeleteAllRequests() error {
-	return c.api.DeleteAllRequests()
-}
-
-// DeleteSentRequests clears sent requests from Client's auth storage.
-func (c *Client) DeleteSentRequests() error {
-	return c.api.DeleteSentRequests()
-}
-
-// DeleteReceiveRequests clears receive requests from Client's auth storage.
-func (c *Client) DeleteReceiveRequests() error {
-	return c.api.DeleteReceiveRequests()
-}
-
-// DeleteContact is a function which removes a contact from Client's storage
-func (c *Client) DeleteContact(b []byte) error {
-	contactObj, err := UnmarshalContact(b)
-	if err != nil {
-		return err
-	}
-	return c.api.DeleteContact(contactObj.c.ID)
-}
-
-// SetProxiedBins updates the host pool filter that filters out gateways that
-// are not in one of the specified bins. The provided bins should be CSV.
-func (c *Client) SetProxiedBins(binStringsCSV string) error {
-	// Convert CSV to slice of strings
-	all, err := csv.NewReader(strings.NewReader(binStringsCSV)).ReadAll()
-	if err != nil {
-		return err
-	}
-
-	binStrings := make([]string, 0, len(all[0]))
-	for _, a := range all {
-		binStrings = append(binStrings, a...)
-	}
-
-	return c.api.SetProxiedBins(binStrings)
-}
-
-// GetPreferredBins returns the geographic bin or bins that the provided two
-// character country code is a part of. The bins are returned as CSV.
-func (c *Client) GetPreferredBins(countryCode string) (string, error) {
-	bins, err := c.api.GetPreferredBins(countryCode)
-	if err != nil {
-		return "", err
-	}
-
-	// Convert the slice of bins to CSV
-	buff := bytes.NewBuffer(nil)
-	csvWriter := csv.NewWriter(buff)
-	err = csvWriter.Write(bins)
-	if err != nil {
-		return "", err
-	}
-	csvWriter.Flush()
-
-	return buff.String(), nil
-}
-
-// GetRateLimitParams retrieves the rate limiting parameters.
-func (c *Client) GetRateLimitParams() (uint32, uint32, int64) {
-	return c.api.GetRateLimitParams()
-}
-
-/*
-// SearchWithHandler is a non-blocking search that also registers
-// a callback interface for user disovery events.
-func (c *Client) SearchWithHandler(data, separator string,
-	searchTypes []byte, hdlr UserDiscoveryHandler) {
-}
-
-
-// RegisterAuthEventsHandler registers a callback interface for channel
-// authentication events.
-func (b *BindingsClient) RegisterAuthEventsHandler(hdlr AuthEventHandler) {
-}
-
-// Search accepts a "separator" separated list of search elements with
-// an associated list of searchTypes. It returns a ContactList which
-// allows you to iterate over the found contact objects.
-func (b *BindingsClient) Search(data, separator string,
-	searchTypes []byte) ContactList {
-	return nil
-}*/
-
-// getSingle is a function which returns the single mananger if it
-// exists or creates a new one, checking appropriate constraints
-// (that the network follower is running) if it needs to make one
-func (c *Client) getSingle() (*old.Manager, error) {
-	c.singleMux.Lock()
-	defer c.singleMux.Unlock()
-	if c.single == nil {
-		apiClient := &c.api
-		c.single = old.NewManager(apiClient)
-		err := apiClient.AddService(c.single.StartProcesses)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	return c.single, nil
-}
-
-// GetInternalClient returns a reference to the client api. This is for internal
-// use only and should not be called by bindings clients.
-func (c *Client) GetInternalClient() api.Client {
-	return c.api
-}
-
-func WrapAPIClient(c *api.Client) *Client {
-	return &Client{api: *c}
-}
-
-// DumpStack returns a string with the stack trace of every running thread.
-func DumpStack() (string, error) {
-	buf := new(bytes.Buffer)
-	err := pprof.Lookup("goroutine").WriteTo(buf, 2)
-	if err != nil {
-		return "", err
-	}
-	return buf.String(), nil
-}
diff --git a/bindings/clientTracker.go b/bindings/clientTracker.go
new file mode 100644
index 0000000000000000000000000000000000000000..563f4957ea3159d86f478cddb19f43e0dac4cf71
--- /dev/null
+++ b/bindings/clientTracker.go
@@ -0,0 +1,54 @@
+package bindings
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/api"
+	"sync"
+)
+
+// clientTracker is a singleton used to keep track of extant clients, allowing
+// for race condition free passing over the bindings
+
+type clientTracker struct {
+	clients map[int]*Client
+	count   int
+	mux     sync.RWMutex
+}
+
+// make makes a client from an API client, assigning it a unique ID
+func (ct *clientTracker) make(c *api.Client) *Client {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	id := ct.count
+	ct.count++
+
+	ct.clients[id] = &Client{
+		api: api.Client{},
+		id:  id,
+	}
+
+	return ct.clients[id]
+}
+
+//get returns a client given its ID
+func (ct *clientTracker) get(id int) (*Client, error) {
+	ct.mux.RLock()
+	defer ct.mux.RUnlock()
+
+	c, exist := ct.clients[id]
+	if !exist {
+		return nil, errors.Errorf("Cannot get client for id %d, client "+
+			"does not exist", id)
+	}
+
+	return c, nil
+}
+
+//deletes a client if it exists
+func (ct *clientTracker) delete(id int) {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	delete(ct.clients, id)
+}
diff --git a/bindings/connect.go b/bindings/connect.go
new file mode 100644
index 0000000000000000000000000000000000000000..c30a64e016e372971a271af8497cbb1ef39d7d29
--- /dev/null
+++ b/bindings/connect.go
@@ -0,0 +1,70 @@
+package bindings
+
+import (
+	"encoding/json"
+	"gitlab.com/elixxir/client/catalog"
+	"gitlab.com/elixxir/client/connect"
+	e2e2 "gitlab.com/elixxir/client/e2e"
+	contact2 "gitlab.com/elixxir/crypto/contact"
+	"gitlab.com/elixxir/crypto/e2e"
+	"gitlab.com/xx_network/primitives/id"
+	"time"
+)
+
+//connection tracker singleton, used to track connections so they can be
+//referenced by id back over the bindings
+var connectionTrackerSingleton = &connectionTracker{
+	connections: make(map[int]Connection),
+	count:       0,
+}
+
+type Connection struct {
+	connection connect.Connection
+	id         int
+}
+
+// Connect blocks until it connects to the remote
+func (c *Client) Connect(recipientContact []byte, myIdentity []byte) (
+	*Connection, error) {
+	cont, err := contact2.Unmarshal(recipientContact)
+	if err != nil {
+		return nil, err
+	}
+	myID, _, _, myDHPriv, err := unmarshalIdentity(myIdentity)
+	if err != nil {
+		return nil, err
+	}
+
+	connection, err := connect.Connect(cont, myID, myDHPriv, c.api.GetRng(),
+		c.api.GetStorage().GetE2EGroup(), c.api.GetCmix(), connect.GetDefaultParams())
+
+	if err != nil {
+		return nil, err
+	}
+
+	return connectionTrackerSingleton.make(connection), nil
+}
+
+type E2ESendReport struct {
+	roundsList
+	MessageID []byte
+	Timestamp int64
+}
+
+func (c *Connection) SendE2E(mt int, payload []byte) ([]byte, error) {
+	rounds, mid, ts, err := c.connection.SendE2E(catalog.MessageType(mt), payload,
+		e2e2.GetDefaultParams())
+
+	if err != nil {
+		return nil, err
+	}
+
+	sr := E2ESendReport{
+		MessageID: mid.Marshal(),
+		Timestamp: ts.UnixNano(),
+	}
+
+	sr.roundsList = makeRoundsList(rounds)
+
+	return json.Marshal(&sr)
+}
diff --git a/bindings/connectionTracker.go b/bindings/connectionTracker.go
new file mode 100644
index 0000000000000000000000000000000000000000..19573ed4e3550a30c4e5d31d997abdc8de2b8bd3
--- /dev/null
+++ b/bindings/connectionTracker.go
@@ -0,0 +1,62 @@
+package bindings
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/connect"
+	"sync"
+)
+
+package bindings
+
+import (
+"github.com/pkg/errors"
+"gitlab.com/elixxir/client/api"
+"sync"
+)
+
+// connectionTracker is a singleton used to keep track of extant clients, allowing
+// for race condition free passing over the bindings
+
+type connectionTracker struct {
+	connections map[int]*Connection
+	count       int
+	mux         sync.RWMutex
+}
+
+// make makes a client from an API client, assigning it a unique ID
+func (ct *connectionTracker) make(c connect.Connection) *Connection {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	id := ct.count
+	ct.count++
+
+	ct.connections[id] = &Connection{
+		connection: c,
+		id:         id,
+	}
+
+	return ct.connections[id]
+}
+
+//get returns a client given its ID
+func (ct *connectionTracker) get(id int) (*Connection, error) {
+	ct.mux.RLock()
+	defer ct.mux.RUnlock()
+
+	c, exist := ct.connections[id]
+	if !exist {
+		return nil, errors.Errorf("Cannot get client for id %d, client "+
+			"does not exist", id)
+	}
+
+	return c, nil
+}
+
+//deletes a client if it exists
+func (ct *connectionTracker) delete(id int) {
+	ct.mux.Lock()
+	defer ct.mux.Unlock()
+
+	delete(ct.connections, id)
+}
diff --git a/bindings/contact.go b/bindings/contact.go
index c02aa2cbfd8b276aa399ee1f7059b0564b7929ba..3f96d3b07b797006bb29a3eb38537c41f9e8e4f0 100644
--- a/bindings/contact.go
+++ b/bindings/contact.go
@@ -1,80 +1,54 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                          //
-//                                                                           //
-// Use of this source code is governed by a license that can be found in the //
-// LICENSE file                                                              //
-///////////////////////////////////////////////////////////////////////////////
-
 package bindings
 
 import (
-	"gitlab.com/elixxir/crypto/contact"
-	"gitlab.com/elixxir/primitives/fact"
+	"encoding/json"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
 )
 
-/* fact object*/
-//creates a new fact. The factType must be either:
-//  0 - Username
-//  1 - Email
-//  2 - Phone Number
-// The fact must be well formed for the type and must not include commas or
-// semicolons. If it is not well formed, it will be rejected.  Phone numbers
-// must have the two letter country codes appended.  For the complete set of
-// validation, see /elixxir/primitives/fact/fact.go
-func NewFact(factType int, factStr string) (*Fact, error) {
-	f, err := fact.NewFact(fact.FactType(factType), factStr)
-	if err != nil {
-		return nil, err
-	}
-	return &Fact{f: &f}, nil
+type Identity struct {
+	ID            []byte
+	RSAPrivatePem []byte
+	Salt          []byte
+	DHKeyPrivate  []byte
 }
 
 type Fact struct {
-	f *fact.Fact
+	Fact string
+	Type string
 }
 
-func (f *Fact) Get() string {
-	return f.f.Fact
+// MakeIdentity generates a new cryptographic identity for receving
+// messages
+func (c *Client) MakeIdentity() ([]byte, error) {
+	I := Identity{}
+	return json.Marshal(&I)
 }
 
-func (f *Fact) Type() int {
-	return int(f.f.T)
+func GetContactFromIdentity(identity string) []byte {
+	I := Identity{}
 }
 
-func (f *Fact) Stringify() string {
-	return f.f.Stringify()
+func unmarshalIdentity(marshaled []byte) (*id.ID, *rsa.PrivateKey, []byte,
+	*cyclic.Int, error) {
+	return nil, nil, nil, nil, nil
 }
 
-/* contact object*/
-type Contact struct {
-	c *contact.Contact
+// SetFactsOnContact replaces the facts on the contact with the passed in facts
+// pass in empty facts in order to clear the facts
+func SetFactsOnContact(contact []byte, facts []byte) []byte {
+	I := Identity{}
 }
 
-// GetID returns the user ID for this user.
-func (c *Contact) GetID() []byte {
-	return c.c.ID.Bytes()
-}
+func GetIDFromContact(contact []byte) []byte {
 
-// GetDHPublicKey returns the public key associated with the Contact.
-func (c *Contact) GetDHPublicKey() []byte {
-	return c.c.DhPubKey.Bytes()
 }
 
-// GetDHPublicKey returns hash of a DH proof of key ownership.
-func (c *Contact) GetOwnershipProof() []byte {
-	return c.c.OwnershipProof
-}
+func GetPubkeyFromContact(contact []byte) []byte {
 
-// Returns a fact list for adding and getting facts to and from the contact
-func (c *Contact) GetFactList() *FactList {
-	return &FactList{c: c.c}
 }
 
-func (c *Contact) Marshal() ([]byte, error) {
-	return c.c.Marshal(), nil
-}
+func GetFactsFromContact(contact []byte) []byte {
 
-// GetAPIContact returns the api contact object. Not exported to bindings.
-func (c *Contact) GetAPIContact() *contact.Contact {
-	return c.c
 }
diff --git a/bindings/delivery.go b/bindings/delivery.go
new file mode 100644
index 0000000000000000000000000000000000000000..1c5b2d01a8c43741cccab422398248c5192d5075
--- /dev/null
+++ b/bindings/delivery.go
@@ -0,0 +1,72 @@
+package bindings
+
+import (
+	"fmt"
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/xx_network/primitives/id"
+	"time"
+)
+
+type roundsList struct {
+	rounds []int
+}
+
+func (rl roundsList) Marshal() []byte {
+
+}
+
+func unmarshalRoundsList(marshaled []byte) []id.Round {
+
+}
+
+func makeRoundsList(rounds []id.Round) roundsList {
+
+}
+
+// WaitForMessageDelivery allows the caller to get notified if the rounds a
+// message was sent in successfully completed. Under the hood, this uses an API
+// which uses the internal round data, network historical round lookup, and
+// waiting on network events to determine what has (or will) occur.
+//
+// The callbacks will return at timeoutMS if no state update occurs
+//
+// This function takes the marshaled send report to ensure a memory leak does
+// not occur as a result of both sides of the bindings holding a reference to
+// the same pointer.
+func (c *Client) WaitForMessageDelivery(marshaledSendReport []byte,
+	mdc MessageDeliveryCallback, timeoutMS int) error {
+	jww.INFO.Printf("WaitForMessageDelivery(%v, _, %v)",
+		marshaledSendReport, timeoutMS)
+	sr, err := UnmarshalSendReport(marshaledSendReport)
+	if err != nil {
+		return errors.New(fmt.Sprintf("Failed to "+
+			"WaitForMessageDelivery callback due to bad Send Report: %+v", err))
+	}
+
+	if sr == nil || sr.rl == nil || len(sr.rl.list) == 0 {
+		return errors.New(fmt.Sprintf("Failed to "+
+			"WaitForMessageDelivery callback due to invalid Send Report "+
+			"unmarshal: %s", string(marshaledSendReport)))
+	}
+
+	f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundLookupStatus) {
+		results := make([]byte, len(sr.rl.list))
+		jww.INFO.Printf("Processing WaitForMessageDelivery report "+
+			"for %v, success: %v, timedout: %v", sr.mid, allRoundsSucceeded,
+			timedOut)
+		for i, r := range sr.rl.list {
+			if result, exists := rounds[r]; exists {
+				results[i] = byte(result)
+			}
+		}
+
+		mdc.EventCallback(sr.mid.Marshal(), allRoundsSucceeded, timedOut, results)
+	}
+
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+
+	err = c.api.GetRoundResults(sr.rl.list, timeout, f)
+
+	return err
+}
diff --git a/bindings/follow.go b/bindings/follow.go
new file mode 100644
index 0000000000000000000000000000000000000000..4ad4620d19d5a385ac9d6b7fbad3efa00716bf5e
--- /dev/null
+++ b/bindings/follow.go
@@ -0,0 +1,110 @@
+package bindings
+
+import (
+	"gitlab.com/xx_network/primitives/netTime"
+	"time"
+)
+
+// StartNetworkFollower kicks off the tracking of the network. It starts
+// long running network client threads and returns an object for checking
+// state and stopping those threads.
+// Call this when returning from sleep and close when going back to
+// sleep.
+// These threads may become a significant drain on battery when offline, ensure
+// they are stopped if there is no internet access
+// Threads Started:
+//   - Network Follower (/network/follow.go)
+//   	tracks the network events and hands them off to workers for handling
+//   - Historical Round Retrieval (/network/rounds/historical.go)
+//		Retrieves data about rounds which are too old to be stored by the client
+//	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
+//		Requests all messages in a given round from the gateway of the last nodes
+//	 - Message Handling Worker Group (/network/message/handle.go)
+//		Decrypts and partitions messages when signals via the Switchboard
+//	 - health Tracker (/network/health)
+//		Via the network instance tracks the state of the network
+//	 - Garbled Messages (/network/message/garbled.go)
+//		Can be signaled to check all recent messages which could be be decoded
+//		Uses a message store on disk for persistence
+//	 - Critical Messages (/network/message/critical.go)
+//		Ensures all protocol layer mandatory messages are sent
+//		Uses a message store on disk for persistence
+//	 - KeyExchange Trigger (/keyExchange/trigger.go)
+//		Responds to sent rekeys and executes them
+//   - KeyExchange Confirm (/keyExchange/confirm.go)
+//		Responds to confirmations of successful rekey operations
+func (c *Client) StartNetworkFollower(timeoutMS int) error {
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+	return c.api.StartNetworkFollower(timeout)
+}
+
+// WaitForNewtwork will block until either the network is healthy or the
+// passed timeout. It will return true if the network is healthy
+func (c *Client) WaitForNetwork(timeoutMS int) bool {
+	start := netTime.Now()
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+	for netTime.Since(start) < timeout {
+		if c.api.GetCmix().IsHealthy() {
+			return true
+		}
+		time.Sleep(250 * time.Millisecond)
+	}
+	return false
+}
+
+// Gets the state of the network follower. Returns:
+// Stopped 	- 0
+// Starting - 1000
+// Running	- 2000
+// Stopping	- 3000
+func (c *Client) NetworkFollowerStatus() int {
+	return int(c.api.NetworkFollowerStatus())
+}
+
+// HasRunningProcessies checks if any background threads are running.
+// returns true if none are running. This is meant to be
+// used when NetworkFollowerStatus() returns Stopping.
+// Due to the handling of comms on iOS, where the OS can
+// block indefiently, it may not enter the stopped
+// state apropreatly. This can be used instead.
+func (c *Client) HasRunningProcessies() bool {
+	return c.api.HasRunningProcessies()
+}
+
+// IsNetworkHealthy returns true if the network is read to be in a healthy state where
+// messages can be sent
+func (c *Client) IsNetworkHealthy() bool {
+	return c.api.GetCmix().IsHealthy()
+}
+
+// A callback when which is used to receive notification if network health
+// changes
+type NetworkHealthCallback interface {
+	Callback(bool)
+}
+
+// RegisterNetworkHealthCB registers the network health callback to be called
+// any time the network health changes. Returns a unique ID that can be used to
+// unregister the network health callback.
+func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) int64 {
+	return int64(c.api.GetCmix().AddHealthCallback(nhc.Callback))
+}
+
+func (c *Client) UnregisterNetworkHealthCB(funcID int64) {
+	c.api.GetCmix().RemoveHealthCallback(uint64(funcID))
+}
+
+type ClientError interface {
+	Report(source, message, trace string)
+}
+
+// RegisterClientErrorCallback registers the callback to handle errors from the
+// long running threads controlled by StartNetworkFollower and StopNetworkFollower
+func (c *Client) RegisterClientErrorCallback(clientError ClientError) {
+	errChan := c.api.GetErrorsChannel()
+	go func() {
+		for report := range errChan {
+			go clientError.Report(report.Source, report.Message, report.Trace)
+		}
+	}()
+}
diff --git a/bindings/README.md b/bindings/old/README.md
similarity index 100%
rename from bindings/README.md
rename to bindings/old/README.md
diff --git a/bindings/authenticatedChannels.go b/bindings/old/authenticatedChannels.go
similarity index 99%
rename from bindings/authenticatedChannels.go
rename to bindings/old/authenticatedChannels.go
index af246b5408736224ec081ae7e45806b25b4a0a60..d64374c40d58f4f65053eb6fbfe144590bb5d7a0 100644
--- a/bindings/authenticatedChannels.go
+++ b/bindings/old/authenticatedChannels.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"fmt"
diff --git a/bindings/backup.go b/bindings/old/backup.go
similarity index 99%
rename from bindings/backup.go
rename to bindings/old/backup.go
index 955839e8cf326ecda83e36fd35f2ba68fdb657f9..e8d890b56acd283f85b90c71e7d0536309b5c078 100644
--- a/bindings/backup.go
+++ b/bindings/old/backup.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                               //
 ////////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/backup"
diff --git a/bindings/callback.go b/bindings/old/callback.go
similarity index 99%
rename from bindings/callback.go
rename to bindings/old/callback.go
index 4ad87c94ae91e1dc5d688900d75d0b404f9a1765..9fd5ca3ae057365f058b2c0a5667c9a8edb03a4e 100644
--- a/bindings/callback.go
+++ b/bindings/old/callback.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/interfaces"
diff --git a/bindings/old/client.go b/bindings/old/client.go
new file mode 100644
index 0000000000000000000000000000000000000000..bd5f31d84321f06346ad37e9f60ba7368073343b
--- /dev/null
+++ b/bindings/old/client.go
@@ -0,0 +1,618 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package old
+
+import (
+	"bytes"
+	"encoding/csv"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/elixxir/client/single/old"
+	"runtime/pprof"
+	"strings"
+	"sync"
+	"time"
+
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/api"
+	"gitlab.com/elixxir/client/interfaces/message"
+	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/crypto/contact"
+	"gitlab.com/elixxir/primitives/states"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/netTime"
+	"google.golang.org/grpc/grpclog"
+)
+
+var extantClient bool = false
+var loginMux sync.Mutex
+
+var clientSingleton *Client
+
+// sets the log level
+func init() {
+	jww.SetLogThreshold(jww.LevelInfo)
+	jww.SetStdoutThreshold(jww.LevelInfo)
+}
+
+// BindingsClient wraps the api.Client, implementing additional functions
+// to support the gomobile Client interface
+type Client struct {
+	api       api.Client
+	single    *old.Manager
+	singleMux sync.Mutex
+}
+
+// NewClient creates client storage, generates keys, connects, and registers
+// with the network. Note that this does not register a username/identity, but
+// merely creates a new cryptographic identity for adding such information
+// at a later date.
+//
+// Users of this function should delete the storage directory on error.
+func NewClient(network, storageDir string, password []byte, regCode string) error {
+	if err := api.NewClient(network, storageDir, password, regCode); err != nil {
+		return errors.New(fmt.Sprintf("Failed to create new client: %+v",
+			err))
+	}
+	return nil
+}
+
+// NewPrecannedClient creates an insecure user with predetermined keys with nodes
+// It creates client storage, generates keys, connects, and registers
+// with the network. Note that this does not register a username/identity, but
+// merely creates a new cryptographic identity for adding such information
+// at a later date.
+//
+// Users of this function should delete the storage directory on error.
+func NewPrecannedClient(precannedID int, network, storageDir string, password []byte) error {
+	if precannedID < 0 {
+		return errors.New("Cannot create precanned client with negative ID")
+	}
+
+	if err := api.NewPrecannedClient(uint(precannedID), network, storageDir, password); err != nil {
+		return errors.New(fmt.Sprintf("Failed to create new precanned "+
+			"client: %+v", err))
+	}
+	return nil
+}
+
+type BackupReport struct {
+	RestoredContacts []*id.ID
+	Params           string
+}
+
+// NewClientFromBackup constructs a new Client from an encrypted backup. The backup
+// is decrypted using the backupPassphrase. On success a successful client creation,
+// the function will return a JSON encoded list of the E2E partners
+// contained in the backup and a json-encoded string of the parameters stored in the backup
+func NewClientFromBackup(ndfJSON, storageDir string, sessionPassword,
+	backupPassphrase, backupFileContents []byte) ([]byte, error) {
+	backupPartnerIds, jsonParams, err := api.NewClientFromBackup(ndfJSON, storageDir,
+		sessionPassword, backupPassphrase, backupFileContents)
+	if err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to create new "+
+			"client from backup: %+v", err))
+	}
+
+	report := BackupReport{
+		RestoredContacts: backupPartnerIds,
+		Params:           jsonParams,
+	}
+
+	return json.Marshal(report)
+}
+
+// Login will load an existing client from the storageDir
+// using the password. This will fail if the client doesn't exist or
+// the password is incorrect.
+// The password is passed as a byte array so that it can be cleared from
+// memory and stored as securely as possible using the memguard library.
+// Login does not block on network connection, and instead loads and
+// starts subprocesses to perform network operations.
+func Login(storageDir string, password []byte, parameters string) (*Client, error) {
+	loginMux.Lock()
+	defer loginMux.Unlock()
+
+	if extantClient {
+		return nil, errors.New("cannot login when another session " +
+			"already exists")
+	}
+	// check if a client is already logged in, refuse to login if one is
+	p, err := params.GetNetworkParameters(parameters)
+	if err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err))
+	}
+
+	client, err := api.Login(storageDir, password, p)
+	if err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err))
+	}
+	extantClient = true
+	clientSingleton := &Client{api: *client}
+
+	return clientSingleton, nil
+}
+
+// returns a previously created client. IF be used if the garbage collector
+// removes the client instance on the app side.  Is NOT thread safe relative to
+// login, newClient, or newPrecannedClient
+func GetClientSingleton() *Client {
+	return clientSingleton
+}
+
+// sets level of logging. All logs the set level and above will be displayed
+// options are:
+//	TRACE		- 0
+//	DEBUG		- 1
+//	INFO 		- 2
+//	WARN		- 3
+//	ERROR		- 4
+//	CRITICAL	- 5
+//	FATAL		- 6
+// The default state without updates is: INFO
+func LogLevel(level int) error {
+	if level < 0 || level > 6 {
+		return errors.New(fmt.Sprintf("log level is not valid: log level: %d", level))
+	}
+
+	threshold := jww.Threshold(level)
+	jww.SetLogThreshold(threshold)
+	jww.SetStdoutThreshold(threshold)
+
+	switch threshold {
+	case jww.LevelTrace:
+		fallthrough
+	case jww.LevelDebug:
+		fallthrough
+	case jww.LevelInfo:
+		jww.INFO.Printf("Log level set to: %s", threshold)
+	case jww.LevelWarn:
+		jww.WARN.Printf("Log level set to: %s", threshold)
+	case jww.LevelError:
+		jww.ERROR.Printf("Log level set to: %s", threshold)
+	case jww.LevelCritical:
+		jww.CRITICAL.Printf("Log level set to: %s", threshold)
+	case jww.LevelFatal:
+		jww.FATAL.Printf("Log level set to: %s", threshold)
+	}
+
+	return nil
+}
+
+//RegisterLogWriter registers a callback on which logs are written.
+func RegisterLogWriter(writer LogWriter) {
+	jww.SetLogOutput(&writerAdapter{lw: writer})
+}
+
+// EnableGrpcLogs sets GRPC trace logging
+func EnableGrpcLogs(writer LogWriter) {
+	logger := &writerAdapter{lw: writer}
+	grpclog.SetLoggerV2(grpclog.NewLoggerV2WithVerbosity(
+		logger, logger, logger, 99))
+}
+
+//Unmarshals a marshaled contact object, returns an error if it fails
+func UnmarshalContact(b []byte) (*Contact, error) {
+	c, err := contact.Unmarshal(b)
+	if err != nil {
+		return nil, errors.New(fmt.Sprintf("Failed to Unmarshal "+
+			"Contact: %+v", err))
+	}
+	return &Contact{c: &c}, nil
+}
+
+//Unmarshals a marshaled send report object, returns an error if it fails
+func UnmarshalSendReport(b []byte) (*SendReport, error) {
+	sr := &SendReport{}
+	return sr, sr.Unmarshal(b)
+}
+
+// StartNetworkFollower kicks off the tracking of the network. It starts
+// long running network client threads and returns an object for checking
+// state and stopping those threads.
+// Call this when returning from sleep and close when going back to
+// sleep.
+// These threads may become a significant drain on battery when offline, ensure
+// they are stopped if there is no internet access
+// Threads Started:
+//   - Network Follower (/network/follow.go)
+//   	tracks the network events and hands them off to workers for handling
+//   - Historical Round Retrieval (/network/rounds/historical.go)
+//		Retrieves data about rounds which are too old to be stored by the client
+//	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
+//		Requests all messages in a given round from the gateway of the last nodes
+//	 - Message Handling Worker Group (/network/message/handle.go)
+//		Decrypts and partitions messages when signals via the Switchboard
+//	 - health Tracker (/network/health)
+//		Via the network instance tracks the state of the network
+//	 - Garbled Messages (/network/message/garbled.go)
+//		Can be signaled to check all recent messages which could be be decoded
+//		Uses a message store on disk for persistence
+//	 - Critical Messages (/network/message/critical.go)
+//		Ensures all protocol layer mandatory messages are sent
+//		Uses a message store on disk for persistence
+//	 - KeyExchange Trigger (/keyExchange/trigger.go)
+//		Responds to sent rekeys and executes them
+//   - KeyExchange Confirm (/keyExchange/confirm.go)
+//		Responds to confirmations of successful rekey operations
+func (c *Client) StartNetworkFollower(timeoutMS int) error {
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+	return c.api.StartNetworkFollower(timeout)
+}
+
+// RegisterClientErrorCallback registers the callback to handle errors from the
+// long running threads controlled by StartNetworkFollower and StopNetworkFollower
+func (c *Client) RegisterClientErrorCallback(clientError ClientError) {
+	errChan := c.api.GetErrorsChannel()
+	go func() {
+		for report := range errChan {
+			go clientError.Report(report.Source, report.Message, report.Trace)
+		}
+	}()
+}
+
+// StopNetworkFollower stops the network follower if it is running.
+// It returns errors if the Follower is in the wrong status to stop or if it
+// fails to stop it.
+// if the network follower is running and this fails, the client object will
+// most likely be in an unrecoverable state and need to be trashed.
+func (c *Client) StopNetworkFollower() error {
+	if err := c.api.StopNetworkFollower(); err != nil {
+		return errors.New(fmt.Sprintf("Failed to stop the "+
+			"network follower: %+v", err))
+	}
+	return nil
+}
+
+// WaitForNewtwork will block until either the network is healthy or the
+// passed timeout. It will return true if the network is healthy
+func (c *Client) WaitForNetwork(timeoutMS int) bool {
+	start := netTime.Now()
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+	for netTime.Since(start) < timeout {
+		if c.api.GetHealth().IsHealthy() {
+			return true
+		}
+		time.Sleep(250 * time.Millisecond)
+	}
+	return false
+}
+
+// Gets the state of the network follower. Returns:
+// Stopped 	- 0
+// Starting - 1000
+// Running	- 2000
+// Stopping	- 3000
+func (c *Client) NetworkFollowerStatus() int {
+	return int(c.api.NetworkFollowerStatus())
+}
+
+// HasRunningProcessies checks if any background threads are running.
+// returns true if none are running. This is meant to be
+// used when NetworkFollowerStatus() returns Stopping.
+// Due to the handling of comms on iOS, where the OS can
+// block indefiently, it may not enter the stopped
+// state apropreatly. This can be used instead.
+func (c *Client) HasRunningProcessies() bool {
+	return c.api.HasRunningProcessies()
+}
+
+// returns true if the network is read to be in a healthy state where
+// messages can be sent
+func (c *Client) IsNetworkHealthy() bool {
+	return c.api.GetHealth().IsHealthy()
+}
+
+// RegisterNetworkHealthCB registers the network health callback to be called
+// any time the network health changes. Returns a unique ID that can be used to
+// unregister the network health callback.
+func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) int64 {
+	return int64(c.api.GetHealth().AddFunc(nhc.Callback))
+}
+
+func (c *Client) UnregisterNetworkHealthCB(funcID int64) {
+	c.api.GetHealth().RemoveFunc(uint64(funcID))
+}
+
+// RegisterListener records and installs a listener for messages
+// matching specific uid, msgType, and/or username
+// Returns a ListenerUnregister interface which can be
+//
+// to register for any userID, pass in an id with length 0 or an id with
+// all zeroes
+//
+// to register for any message type, pass in a message type of 0
+//
+// Message Types can be found in client/interfaces/message/type.go
+// Make sure to not conflict with ANY default message types
+func (c *Client) RegisterListener(uid []byte, msgType int,
+	listener Listener) (*Unregister, error) {
+	jww.INFO.Printf("RegisterListener(%v, %d)", uid,
+		msgType)
+
+	name := listener.Name()
+
+	var u *id.ID
+	if len(uid) == 0 {
+		u = &id.ID{}
+	} else {
+		var err error
+		u, err = id.Unmarshal(uid)
+		if err != nil {
+			return nil, errors.New(fmt.Sprintf("Failed to "+
+				"ResgisterListener: %+v", err))
+		}
+	}
+
+	mt := message.Type(msgType)
+
+	f := func(item message.Receive) {
+		listener.Hear(&Message{r: item})
+	}
+
+	lid := c.api.GetSwitchboard().RegisterFunc(name, u, mt, f)
+
+	return newListenerUnregister(lid, c.api.GetSwitchboard()), nil
+}
+
+// RegisterRoundEventsHandler registers a callback interface for round
+// events.
+// The rid is the round the event attaches to
+// The timeoutMS is the number of milliseconds until the event fails, and the
+// validStates are a list of states (one per byte) on which the event gets
+// triggered
+// States:
+//  0x00 - PENDING (Never seen by client)
+//  0x01 - PRECOMPUTING
+//  0x02 - STANDBY
+//  0x03 - QUEUED
+//  0x04 - REALTIME
+//  0x05 - COMPLETED
+//  0x06 - FAILED
+// These states are defined in elixxir/primitives/states/state.go
+func (c *Client) RegisterRoundEventsHandler(rid int, cb RoundEventCallback,
+	timeoutMS int, il *IntList) *Unregister {
+
+	rcb := func(ri *mixmessages.RoundInfo, timedOut bool) {
+		cb.EventCallback(int(ri.ID), int(ri.State), timedOut)
+	}
+
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+
+	vStates := make([]states.Round, len(il.lst))
+	for i, s := range il.lst {
+		vStates[i] = states.Round(s)
+	}
+
+	roundID := id.Round(rid)
+
+	ec := c.api.GetRoundEvents().AddRoundEvent(roundID, rcb, timeout)
+
+	return newRoundUnregister(roundID, ec, c.api.GetRoundEvents())
+}
+
+// WaitForRoundCompletion allows the caller to get notified if a round
+// has completed (or failed). Under the hood, this uses an API which uses the internal
+// round data, network historical round lookup, and waiting on network events
+// to determine what has (or will) occur.
+//
+// The callbacks will return at timeoutMS if no state update occurs
+func (c *Client) WaitForRoundCompletion(roundID int,
+	rec RoundCompletionCallback, timeoutMS int) error {
+
+	f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundLookupStatus) {
+		rec.EventCallback(roundID, allRoundsSucceeded, timedOut)
+	}
+
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+
+	return c.api.GetRoundResults([]id.Round{id.Round(roundID)}, timeout, f)
+}
+
+// WaitForMessageDelivery allows the caller to get notified if the rounds a
+// message was sent in successfully completed. Under the hood, this uses an API
+// which uses the internal round data, network historical round lookup, and
+// waiting on network events to determine what has (or will) occur.
+//
+// The callbacks will return at timeoutMS if no state update occurs
+//
+// This function takes the marshaled send report to ensure a memory leak does
+// not occur as a result of both sides of the bindings holding a reference to
+// the same pointer.
+func (c *Client) WaitForMessageDelivery(marshaledSendReport []byte,
+	mdc MessageDeliveryCallback, timeoutMS int) error {
+	jww.INFO.Printf("WaitForMessageDelivery(%v, _, %v)",
+		marshaledSendReport, timeoutMS)
+	sr, err := UnmarshalSendReport(marshaledSendReport)
+	if err != nil {
+		return errors.New(fmt.Sprintf("Failed to "+
+			"WaitForMessageDelivery callback due to bad Send Report: %+v", err))
+	}
+
+	if sr == nil || sr.rl == nil || len(sr.rl.list) == 0 {
+		return errors.New(fmt.Sprintf("Failed to "+
+			"WaitForMessageDelivery callback due to invalid Send Report "+
+			"unmarshal: %s", string(marshaledSendReport)))
+	}
+
+	f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundLookupStatus) {
+		results := make([]byte, len(sr.rl.list))
+		jww.INFO.Printf("Processing WaitForMessageDelivery report "+
+			"for %v, success: %v, timedout: %v", sr.mid, allRoundsSucceeded,
+			timedOut)
+		for i, r := range sr.rl.list {
+			if result, exists := rounds[r]; exists {
+				results[i] = byte(result)
+			}
+		}
+
+		mdc.EventCallback(sr.mid.Marshal(), allRoundsSucceeded, timedOut, results)
+	}
+
+	timeout := time.Duration(timeoutMS) * time.Millisecond
+
+	err = c.api.GetRoundResults(sr.rl.list, timeout, f)
+
+	return err
+}
+
+// Returns a user object from which all information about the current user
+// can be gleaned
+func (c *Client) GetUser() *User {
+	u := c.api.GetUser()
+	return &User{u: &u}
+}
+
+// GetNodeRegistrationStatus returns a struct with the number of nodes the
+// client is registered with and the number total.
+func (c *Client) GetNodeRegistrationStatus() (*NodeRegistrationsStatus, error) {
+	registered, total, err := c.api.GetNodeRegistrationStatus()
+
+	return &NodeRegistrationsStatus{registered, total}, err
+}
+
+// DeleteRequest will delete a request, agnostic of request type
+// for the given partner ID. If no request exists for this
+// partner ID an error will be returned.
+func (c *Client) DeleteRequest(requesterUserId []byte) error {
+	requesterId, err := id.Unmarshal(requesterUserId)
+	if err != nil {
+		return err
+	}
+
+	jww.DEBUG.Printf("Deleting request for partner ID: %s", requesterId)
+	return c.api.DeleteRequest(requesterId)
+}
+
+// DeleteAllRequests clears all requests from Client's auth storage.
+func (c *Client) DeleteAllRequests() error {
+	return c.api.DeleteAllRequests()
+}
+
+// DeleteSentRequests clears sent requests from Client's auth storage.
+func (c *Client) DeleteSentRequests() error {
+	return c.api.DeleteSentRequests()
+}
+
+// DeleteReceiveRequests clears receive requests from Client's auth storage.
+func (c *Client) DeleteReceiveRequests() error {
+	return c.api.DeleteReceiveRequests()
+}
+
+// DeleteContact is a function which removes a contact from Client's storage
+func (c *Client) DeleteContact(b []byte) error {
+	contactObj, err := UnmarshalContact(b)
+	if err != nil {
+		return err
+	}
+	return c.api.DeleteContact(contactObj.c.ID)
+}
+
+// SetProxiedBins updates the host pool filter that filters out gateways that
+// are not in one of the specified bins. The provided bins should be CSV.
+func (c *Client) SetProxiedBins(binStringsCSV string) error {
+	// Convert CSV to slice of strings
+	all, err := csv.NewReader(strings.NewReader(binStringsCSV)).ReadAll()
+	if err != nil {
+		return err
+	}
+
+	binStrings := make([]string, 0, len(all[0]))
+	for _, a := range all {
+		binStrings = append(binStrings, a...)
+	}
+
+	return c.api.SetProxiedBins(binStrings)
+}
+
+// GetPreferredBins returns the geographic bin or bins that the provided two
+// character country code is a part of. The bins are returned as CSV.
+func (c *Client) GetPreferredBins(countryCode string) (string, error) {
+	bins, err := c.api.GetPreferredBins(countryCode)
+	if err != nil {
+		return "", err
+	}
+
+	// Convert the slice of bins to CSV
+	buff := bytes.NewBuffer(nil)
+	csvWriter := csv.NewWriter(buff)
+	err = csvWriter.Write(bins)
+	if err != nil {
+		return "", err
+	}
+	csvWriter.Flush()
+
+	return buff.String(), nil
+}
+
+// GetRateLimitParams retrieves the rate limiting parameters.
+func (c *Client) GetRateLimitParams() (uint32, uint32, int64) {
+	return c.api.GetRateLimitParams()
+}
+
+/*
+// SearchWithHandler is a non-blocking search that also registers
+// a callback interface for user disovery events.
+func (c *Client) SearchWithHandler(data, separator string,
+	searchTypes []byte, hdlr UserDiscoveryHandler) {
+}
+
+
+// RegisterAuthEventsHandler registers a callback interface for channel
+// authentication events.
+func (b *BindingsClient) RegisterAuthEventsHandler(hdlr AuthEventHandler) {
+}
+
+// Search accepts a "separator" separated list of search elements with
+// an associated list of searchTypes. It returns a ContactList which
+// allows you to iterate over the found contact objects.
+func (b *BindingsClient) Search(data, separator string,
+	searchTypes []byte) ContactList {
+	return nil
+}*/
+
+// getSingle is a function which returns the single mananger if it
+// exists or creates a new one, checking appropriate constraints
+// (that the network follower is running) if it needs to make one
+func (c *Client) getSingle() (*old.Manager, error) {
+	c.singleMux.Lock()
+	defer c.singleMux.Unlock()
+	if c.single == nil {
+		apiClient := &c.api
+		c.single = old.NewManager(apiClient)
+		err := apiClient.AddService(c.single.StartProcesses)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return c.single, nil
+}
+
+// GetInternalClient returns a reference to the client api. This is for internal
+// use only and should not be called by bindings clients.
+func (c *Client) GetInternalClient() api.Client {
+	return c.api
+}
+
+func WrapAPIClient(c *api.Client) *Client {
+	return &Client{api: *c}
+}
+
+// DumpStack returns a string with the stack trace of every running thread.
+func DumpStack() (string, error) {
+	buf := new(bytes.Buffer)
+	err := pprof.Lookup("goroutine").WriteTo(buf, 2)
+	if err != nil {
+		return "", err
+	}
+	return buf.String(), nil
+}
diff --git a/bindings/old/contact.go b/bindings/old/contact.go
new file mode 100644
index 0000000000000000000000000000000000000000..30fcdcc92c1a9d8b5146d6e9c2f049b7c5368ef3
--- /dev/null
+++ b/bindings/old/contact.go
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package old
+
+import (
+	"gitlab.com/elixxir/crypto/contact"
+	"gitlab.com/elixxir/primitives/fact"
+)
+
+/* fact object*/
+//creates a new fact. The factType must be either:
+//  0 - Username
+//  1 - Email
+//  2 - Phone Number
+// The fact must be well formed for the type and must not include commas or
+// semicolons. If it is not well formed, it will be rejected.  Phone numbers
+// must have the two letter country codes appended.  For the complete set of
+// validation, see /elixxir/primitives/fact/fact.go
+func NewFact(factType int, factStr string) (*Fact, error) {
+	f, err := fact.NewFact(fact.FactType(factType), factStr)
+	if err != nil {
+		return nil, err
+	}
+	return &Fact{f: &f}, nil
+}
+
+type Fact struct {
+	f *fact.Fact
+}
+
+func (f *Fact) Get() string {
+	return f.f.Fact
+}
+
+func (f *Fact) Type() int {
+	return int(f.f.T)
+}
+
+func (f *Fact) Stringify() string {
+	return f.f.Stringify()
+}
+
+/* contact object*/
+type Contact struct {
+	c *contact.Contact
+}
+
+// GetID returns the user ID for this user.
+func (c *Contact) GetID() []byte {
+	return c.c.ID.Bytes()
+}
+
+// GetDHPublicKey returns the public key associated with the Contact.
+func (c *Contact) GetDHPublicKey() []byte {
+	return c.c.DhPubKey.Bytes()
+}
+
+// GetDHPublicKey returns hash of a DH proof of key ownership.
+func (c *Contact) GetOwnershipProof() []byte {
+	return c.c.OwnershipProof
+}
+
+// Returns a fact list for adding and getting facts to and from the contact
+func (c *Contact) GetFactList() *FactList {
+	return &FactList{c: c.c}
+}
+
+func (c *Contact) Marshal() ([]byte, error) {
+	return c.c.Marshal(), nil
+}
+
+// GetAPIContact returns the api contact object. Not exported to bindings.
+func (c *Contact) GetAPIContact() *contact.Contact {
+	return c.c
+}
diff --git a/bindings/dummy.go b/bindings/old/dummy.go
similarity index 99%
rename from bindings/dummy.go
rename to bindings/old/dummy.go
index d6facc68e00687b9a951ce7793b62102b155d3f6..e393cf33b8da90d9b098af8d39be876f63ad8cc1 100644
--- a/bindings/dummy.go
+++ b/bindings/old/dummy.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                               //
 ////////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/dummy"
diff --git a/bindings/errors.go b/bindings/old/errors.go
similarity index 99%
rename from bindings/errors.go
rename to bindings/old/errors.go
index cfffaf0155a8993787120d0bce24f6c1071baeb2..fa23b314fc3dd1a36f53fb09b5e334d24982409b 100644
--- a/bindings/errors.go
+++ b/bindings/old/errors.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"context"
diff --git a/bindings/errors_test.go b/bindings/old/errors_test.go
similarity index 99%
rename from bindings/errors_test.go
rename to bindings/old/errors_test.go
index d93a9924fb336e68fbe6c31af30174709f049d8d..c06ef20dfc2db495b26d96cdaebb83ec32d3cf85 100644
--- a/bindings/errors_test.go
+++ b/bindings/old/errors_test.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"context"
diff --git a/bindings/event.go b/bindings/old/event.go
similarity index 98%
rename from bindings/event.go
rename to bindings/old/event.go
index 4f5aeacf907edfb09f23662e986607c9d820633c..9c261d9d6db9611b3360ae23ce851b78306cd374 100644
--- a/bindings/event.go
+++ b/bindings/old/event.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 // EventCallbackFunctionObject bindings interface which contains function
 // that implements the EventCallbackFunction
diff --git a/bindings/fileTransfer.go b/bindings/old/fileTransfer.go
similarity index 99%
rename from bindings/fileTransfer.go
rename to bindings/old/fileTransfer.go
index 9e2d76169cd393422039b06de483905bd3a0de76..57ea3ed36d2d23c635347ecd5b5ffd12992310b3 100644
--- a/bindings/fileTransfer.go
+++ b/bindings/old/fileTransfer.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                               //
 ////////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"encoding/json"
diff --git a/bindings/group.go b/bindings/old/group.go
similarity index 99%
rename from bindings/group.go
rename to bindings/old/group.go
index 3fce2e43b790c06dc64e0eb15490b5d795746060..edb7b776c0846844c2315796690f94108708faa8 100644
--- a/bindings/group.go
+++ b/bindings/old/group.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"encoding/json"
diff --git a/bindings/jsons.go b/bindings/old/jsons.go
similarity index 98%
rename from bindings/jsons.go
rename to bindings/old/jsons.go
index 53f15435c6e8750a5d08e18c18d23b81c4304f5d..049ced794b15f7355de718f1bc935d5f040cba71 100644
--- a/bindings/jsons.go
+++ b/bindings/old/jsons.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"io/ioutil"
diff --git a/bindings/jsons_test.go b/bindings/old/jsons_test.go
similarity index 98%
rename from bindings/jsons_test.go
rename to bindings/old/jsons_test.go
index a4405fd47fcd0908c0b8acff7a234b7732778e0f..917816613604b638e1bf6096406652745836fa7b 100644
--- a/bindings/jsons_test.go
+++ b/bindings/old/jsons_test.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"fmt"
diff --git a/bindings/list.go b/bindings/old/list.go
similarity index 99%
rename from bindings/list.go
rename to bindings/old/list.go
index 1331c378e2b2f31c457ef2f3d082c51e186f2fbb..c4b5d82282ff6f7bbcfa96a9dc7480df47b5064c 100644
--- a/bindings/list.go
+++ b/bindings/old/list.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"github.com/pkg/errors"
diff --git a/bindings/message.go b/bindings/old/message.go
similarity index 99%
rename from bindings/message.go
rename to bindings/old/message.go
index 3eee3b343627338fb907ba81b93fe2e73f8f4731..2a01ef8db7042a4464ea01d3b4d7bc85eb004065 100644
--- a/bindings/message.go
+++ b/bindings/old/message.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/interfaces/message"
diff --git a/bindings/mnemonic.go b/bindings/old/mnemonic.go
similarity index 99%
rename from bindings/mnemonic.go
rename to bindings/old/mnemonic.go
index 7062341a1958bb3cd2c0e0e9a960b454f1a143cf..6588270347ef1c892c7a7429848a01b2704a1f3e 100644
--- a/bindings/mnemonic.go
+++ b/bindings/old/mnemonic.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import "gitlab.com/elixxir/client/api"
 
diff --git a/bindings/ndf.go b/bindings/old/ndf.go
similarity index 98%
rename from bindings/ndf.go
rename to bindings/old/ndf.go
index 2c35c681799b251796fd7f4592311572468208b3..2b3bb21ba2b88f54f9587343fa888f32059fe586 100644
--- a/bindings/ndf.go
+++ b/bindings/old/ndf.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/api"
diff --git a/bindings/ndf_test.go b/bindings/old/ndf_test.go
similarity index 99%
rename from bindings/ndf_test.go
rename to bindings/old/ndf_test.go
index 3f7c68f26079621e63fe864587da5072ad04b22b..6aa788566a7479d96d3601bc8b0658bdbb501337 100644
--- a/bindings/ndf_test.go
+++ b/bindings/old/ndf_test.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"fmt"
diff --git a/bindings/notifications.go b/bindings/old/notifications.go
similarity index 99%
rename from bindings/notifications.go
rename to bindings/old/notifications.go
index 62cf55faea8eb127dddf116303a2153c41c16906..96df0171077284a505825ffa8b9da82a8b6f22c5 100644
--- a/bindings/notifications.go
+++ b/bindings/old/notifications.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"encoding/json"
diff --git a/bindings/notifications_test.go b/bindings/old/notifications_test.go
similarity index 99%
rename from bindings/notifications_test.go
rename to bindings/old/notifications_test.go
index b180d09d78f5acedfdd1a1eacd0a2356ede18106..e1c09a6be6e1d24a2be4f94e21ed2398a784c7ca 100644
--- a/bindings/notifications_test.go
+++ b/bindings/old/notifications_test.go
@@ -1,4 +1,4 @@
-package bindings
+package old
 
 import (
 	"bytes"
diff --git a/bindings/params.go b/bindings/old/params.go
similarity index 98%
rename from bindings/params.go
rename to bindings/old/params.go
index d4896a2e9e89c49c177689c85ff0a2cf410f9277..2b78f76abd934075503364b58377215d5676f287 100644
--- a/bindings/params.go
+++ b/bindings/old/params.go
@@ -7,7 +7,7 @@
 
 // Contains params-related bindings
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/interfaces/params"
diff --git a/bindings/preimage.go b/bindings/old/preimage.go
similarity index 98%
rename from bindings/preimage.go
rename to bindings/old/preimage.go
index c5b7f60ab1e93e594664b86f9e6a0aa116f17b18..3c84f42d0c19cdcf55d10fc09f952bb91af1599c 100644
--- a/bindings/preimage.go
+++ b/bindings/old/preimage.go
@@ -1,4 +1,4 @@
-package bindings
+package old
 
 import (
 	"encoding/json"
diff --git a/bindings/registrationStatus.go b/bindings/old/registrationStatus.go
similarity index 98%
rename from bindings/registrationStatus.go
rename to bindings/old/registrationStatus.go
index eab2590984413d014695f1489989ae805653fff3..66c100acc2821779cc0b462c6b31ccae2ae8f94f 100644
--- a/bindings/registrationStatus.go
+++ b/bindings/old/registrationStatus.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 // NodeRegistrationsStatus structure for returning nodes registration statuses
 // for bindings.
diff --git a/bindings/restoreContacts.go b/bindings/old/restoreContacts.go
similarity index 99%
rename from bindings/restoreContacts.go
rename to bindings/old/restoreContacts.go
index b970c77a2ed8cbf5664f76a6754904edb9b8d0f0..ff1fae2388de69395088eea86e3033bd1ac92b57 100644
--- a/bindings/restoreContacts.go
+++ b/bindings/old/restoreContacts.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/xxmutils"
diff --git a/bindings/secrets.go b/bindings/old/secrets.go
similarity index 98%
rename from bindings/secrets.go
rename to bindings/old/secrets.go
index 5bdeeed03c35cf6e0af99b8a64aaf54f213e8a23..5ef85b2a870aa658283bdb0903a27d6ff8aa5801 100644
--- a/bindings/secrets.go
+++ b/bindings/old/secrets.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	jww "github.com/spf13/jwalterweatherman"
diff --git a/bindings/secrets_test.go b/bindings/old/secrets_test.go
similarity index 98%
rename from bindings/secrets_test.go
rename to bindings/old/secrets_test.go
index 20e1a7d51f1b182fc44df8902e85d462b615b64b..1887f9564c1ab52058dc5b6eec0ccf96855cd4c3 100644
--- a/bindings/secrets_test.go
+++ b/bindings/old/secrets_test.go
@@ -4,7 +4,7 @@
 // Use of this source code is governed by a license that can be found in the LICENSE file //
 ////////////////////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"bytes"
diff --git a/bindings/send.go b/bindings/old/send.go
similarity index 99%
rename from bindings/send.go
rename to bindings/old/send.go
index 3b85a34b0f05fe6f119a7d45ffe4f195604fb8e3..99ff614ce3ed77ca6247868c4fe92a3f8d4b1d1c 100644
--- a/bindings/send.go
+++ b/bindings/old/send.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"encoding/json"
diff --git a/bindings/timeNow.go b/bindings/old/timeNow.go
similarity index 97%
rename from bindings/timeNow.go
rename to bindings/old/timeNow.go
index fc457b459ae43452a1920c26a8b9e24c53725d74..b8a15b7d8105203fd06dc6c48ceec4163fdcf4e6 100644
--- a/bindings/timeNow.go
+++ b/bindings/old/timeNow.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/xx_network/primitives/netTime"
diff --git a/bindings/ud.go b/bindings/old/ud.go
similarity index 99%
rename from bindings/ud.go
rename to bindings/old/ud.go
index ea8f5390abb2b749d14c50b10ec21b9bf8e596d5..6f2f93fd82397937bb06a54fda3ed7db8f7e0dd2 100644
--- a/bindings/ud.go
+++ b/bindings/old/ud.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"fmt"
diff --git a/bindings/url.go b/bindings/old/url.go
similarity index 97%
rename from bindings/url.go
rename to bindings/old/url.go
index f561540f3ecf89fb1b67e139549208884fe46779..b4b0db76bc113f9f00910988567ce852f32d82cb 100644
--- a/bindings/url.go
+++ b/bindings/old/url.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"fmt"
diff --git a/bindings/user.go b/bindings/old/user.go
similarity index 99%
rename from bindings/user.go
rename to bindings/old/user.go
index c049eaeb141d9b19b2acb8772303edf2ba7c6ed9..0338236eb84fe019fab0767333247216b443b3a5 100644
--- a/bindings/user.go
+++ b/bindings/old/user.go
@@ -5,7 +5,7 @@
 // LICENSE file                                                              //
 ///////////////////////////////////////////////////////////////////////////////
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/interfaces/user"
diff --git a/bindings/utils.go b/bindings/old/utils.go
similarity index 98%
rename from bindings/utils.go
rename to bindings/old/utils.go
index ddf302b237d3f38dc3aa7795aa8f2624bc86f470..c7cb1ebd04375887f46dab870d6cd940e2a631f1 100644
--- a/bindings/utils.go
+++ b/bindings/old/utils.go
@@ -6,7 +6,7 @@
 
 // Provides various utility functions for access over the bindings
 
-package bindings
+package old
 
 import (
 	"gitlab.com/elixxir/client/api/messenger"
diff --git a/bindings/version.go b/bindings/old/version.go
similarity index 95%
rename from bindings/version.go
rename to bindings/old/version.go
index ec517de07f5d262e8e761e85e39bcd68d83914b9..9501a3a00473c2898c84fbdb1224cc2445ab0b97 100644
--- a/bindings/version.go
+++ b/bindings/old/version.go
@@ -1,4 +1,4 @@
-package bindings
+package old
 
 import "gitlab.com/elixxir/client/api"
 
diff --git a/bindings/utilities.go b/bindings/utilities.go
new file mode 100644
index 0000000000000000000000000000000000000000..96c7b346e6a920109d5678fa9802fe5fdfa37435
--- /dev/null
+++ b/bindings/utilities.go
@@ -0,0 +1,72 @@
+package bindings
+
+import (
+	"fmt"
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
+	"google.golang.org/grpc/grpclog"
+)
+
+// sets level of logging. All logs the set level and above will be displayed
+// options are:
+//	TRACE		- 0
+//	DEBUG		- 1
+//	INFO 		- 2
+//	WARN		- 3
+//	ERROR		- 4
+//	CRITICAL	- 5
+//	FATAL		- 6
+// The default state without updates is: INFO
+func LogLevel(level int) error {
+	if level < 0 || level > 6 {
+		return errors.New(fmt.Sprintf("log level is not valid: log level: %d", level))
+	}
+
+	threshold := jww.Threshold(level)
+	jww.SetLogThreshold(threshold)
+	jww.SetStdoutThreshold(threshold)
+
+	switch threshold {
+	case jww.LevelTrace:
+		fallthrough
+	case jww.LevelDebug:
+		fallthrough
+	case jww.LevelInfo:
+		jww.INFO.Printf("Log level set to: %s", threshold)
+	case jww.LevelWarn:
+		jww.WARN.Printf("Log level set to: %s", threshold)
+	case jww.LevelError:
+		jww.ERROR.Printf("Log level set to: %s", threshold)
+	case jww.LevelCritical:
+		jww.CRITICAL.Printf("Log level set to: %s", threshold)
+	case jww.LevelFatal:
+		jww.FATAL.Printf("Log level set to: %s", threshold)
+	}
+
+	return nil
+}
+
+type LogWriter interface {
+	Log(string)
+}
+
+//RegisterLogWriter registers a callback on which logs are written.
+func RegisterLogWriter(writer LogWriter) {
+	jww.SetLogOutput(&writerAdapter{lw: writer})
+}
+
+// EnableGrpcLogs sets GRPC trace logging
+func EnableGrpcLogs(writer LogWriter) {
+	logger := &writerAdapter{lw: writer}
+	grpclog.SetLoggerV2(grpclog.NewLoggerV2WithVerbosity(
+		logger, logger, logger, 99))
+}
+
+type writerAdapter struct {
+	lw LogWriter
+}
+
+func (wa *writerAdapter) Write(p []byte) (n int, err error) {
+	wa.lw.Log(string(p))
+	return len(p), nil
+}