diff --git a/extras/jsonrpc/daemon.go b/extras/jsonrpc/daemon.go index 11b583f..7b11d23 100644 --- a/extras/jsonrpc/daemon.go +++ b/extras/jsonrpc/daemon.go @@ -137,11 +137,17 @@ func (d *Client) SetRPCTimeout(timeout time.Duration) { //============================================ // NEW SDK //============================================ + func (d *Client) AccountList() (*AccountListResponse, error) { response := new(AccountListResponse) return response, d.call(response, "account_list", map[string]interface{}{}) } +func (d *Client) AccountListForWallet(walletID string) (*AccountListResponse, error) { + response := new(AccountListResponse) + return response, d.call(response, "account_list", map[string]interface{}{"wallet_id": walletID}) +} + func (d *Client) SingleAccountList(accountID string) (*Account, error) { response := new(Account) return response, d.call(response, "account_list", map[string]interface{}{"account_id": accountID}) @@ -211,7 +217,7 @@ func (d *Client) AddressUnused(account *string) (*AddressUnusedResponse, error) }) } -func (d *Client) ChannelList(account *string, page uint64, pageSize uint64) (*ChannelListResponse, error) { +func (d *Client) ChannelList(account *string, page uint64, pageSize uint64, wid *string) (*ChannelListResponse, error) { if page == 0 { return nil, errors.Err("pages start from 1") } @@ -221,6 +227,7 @@ func (d *Client) ChannelList(account *string, page uint64, pageSize uint64) (*Ch "page": page, "page_size": pageSize, "include_protobuf": true, + "wallet_id": wid, }) } @@ -521,6 +528,14 @@ func (d *Client) ChannelExport(channelClaimID string, channelName, accountID *st }) } +func (d *Client) ChannelImport(key string, walletID *string) (*ChannelImportResponse, error) { + response := new(ChannelImportResponse) + return response, d.call(response, "channel_import", map[string]interface{}{ + "channel_data": key, + "wallet_id": walletID, + }) +} + func (d *Client) SupportList(accountID *string, page uint64, pageSize uint64) (*SupportListResponse, error) { response := new(SupportListResponse) return response, d.call(response, "support_list", map[string]interface{}{ @@ -598,3 +613,39 @@ func (d *Client) AccountAdd(accountName string, seed *string, privateKey *string structs.DefaultTagName = "json" return response, d.call(response, "account_add", structs.Map(args)) } + +type WalletCreateOpts struct { + ID string `json:"wallet_id"` + SkipOnStartup bool `json:"skip_on_startup,omitempty"` + CreateAccount bool `json:"create_account,omitempty"` + SingleKey bool `json:"single_key,omitempty"` +} + +func (d *Client) WalletCreate(id string, opts *WalletCreateOpts) (*Wallet, error) { + response := new(Wallet) + if opts == nil { + opts = &WalletCreateOpts{} + } + opts.ID = id + structs.DefaultTagName = "json" + return response, d.call(response, "wallet_create", structs.Map(opts)) +} + +func (d *Client) WalletAdd(id string) (*Wallet, error) { + response := new(Wallet) + return response, d.call(response, "wallet_add", map[string]interface{}{"wallet_id": id}) +} + +func (d *Client) WalletList(id string) (*WalletList, error) { + response := new(WalletList) + params := map[string]interface{}{} + if id != "" { + params["wallet_id"] = id + } + return response, d.call(response, "wallet_list", params) +} + +func (d *Client) WalletRemove(id string) (*Wallet, error) { + response := new(Wallet) + return response, d.call(response, "wallet_remove", map[string]interface{}{"wallet_id": id}) +} diff --git a/extras/jsonrpc/daemon_test.go b/extras/jsonrpc/daemon_test.go index fe9d17a..e8ef812 100644 --- a/extras/jsonrpc/daemon_test.go +++ b/extras/jsonrpc/daemon_test.go @@ -3,6 +3,7 @@ package jsonrpc import ( "encoding/json" "fmt" + "math/rand" "os" "strconv" "strings" @@ -21,6 +22,12 @@ func prettyPrint(i interface{}) { fmt.Println(string(s)) } +func TestMain(m *testing.M) { + rand.Seed(time.Now().UnixNano()) + code := m.Run() + os.Exit(code) +} + func TestClient_AccountFund(t *testing.T) { d := NewClient("") accounts, err := d.AccountList() @@ -59,17 +66,20 @@ func TestClient_AccountList(t *testing.T) { func TestClient_SingleAccountList(t *testing.T) { d := NewClient("") - createdAccount, err := d.AccountCreate("test"+fmt.Sprintf("%d", time.Now().Unix())+"@lbry.com", false) + name := "test" + fmt.Sprintf("%d", rand.Int()) + "@lbry.com" + createdAccount, err := d.AccountCreate(name, false) if err != nil { t.Fatal(err) - return } account, err := d.SingleAccountList(createdAccount.ID) + prettyPrint(*createdAccount) + prettyPrint(*account) if err != nil { t.Fatal(err) - return } - prettyPrint(*account) + if account.Name != name { + t.Fatalf("account name mismatch: %v != %v", account.Name, name) + } } func TestClient_AccountBalance(t *testing.T) { @@ -94,7 +104,7 @@ func TestClient_AddressUnused(t *testing.T) { func TestClient_ChannelList(t *testing.T) { d := NewClient("") - got, err := d.ChannelList(nil, 1, 50) + got, err := d.ChannelList(nil, 1, 50, nil) if err != nil { t.Error(err) return @@ -433,7 +443,7 @@ func TestClient_AccountSet(t *testing.T) { func TestClient_AccountCreate(t *testing.T) { d := NewClient("") - name := "test" + fmt.Sprintf("%d", time.Now().Unix()) + "@lbry.com" + name := "lbry#user#id:" + fmt.Sprintf("%d", rand.Int()) account, err := d.AccountCreate(name, false) if err != nil { t.Fatal(err) @@ -468,7 +478,8 @@ func TestClient_AccountAdd(t *testing.T) { func TestClient_AccountRemove(t *testing.T) { d := NewClient("") - createdAccount, err := d.AccountCreate("test"+fmt.Sprintf("%d", time.Now().Unix())+"@lbry.com", false) + name := "lbry#user#id:" + fmt.Sprintf("%d", rand.Int()) + createdAccount, err := d.AccountCreate(name, false) if err != nil { t.Fatal(err) return @@ -488,9 +499,7 @@ func TestClient_AccountRemove(t *testing.T) { prettyPrint(*removedAccount) return } - - t.Error(err) - return + t.Fatal(err) } t.Error("account was not removed") prettyPrint(*account) @@ -507,3 +516,160 @@ func TestClient_ChannelExport(t *testing.T) { } t.Log("Export:", *response) } + +func TestClient_ChannelImport(t *testing.T) { + d := NewClient("") + + // A channel created just for automated testing purposes + channelName := "@LbryAutomatedTestChannel" + channelkey := "7943FWPBHZES4dUcMXSpDYwoM5a2tsyJT1R8V54QoUhekGcqmeH3hbzDXoLLQ8" + + "oKkfb99PgGK5efrZeYqaxg4X5XRJMJ6gKC8hqKcnwhYkmKDXmoBDNgd2ccZ9jhP8z" + + "HG3NJorAN9Hh4XMyBc5goBLZYYvC9MYvBmT3Fcteb5saqMvmQxFURv74NqXLQZC1t" + + "p6iRZKfTj77Pd5gsBsCYAbVmCqzbm5m1hHkUmfFEZVGcQNTYCDwZn543xSMYvSPnJ" + + "zt8tRYCJWaPdj713uENZZMo3gxuAMb1NwSnx8tbwETp7WPkpFLL6HZ9jKpB8BURHM" + + "F1RFD1PRyqbC6YezPyPQ2oninKKHdBduvXZG5KF2G2Q3ixsuE2ntifBBo1f5PotRk" + + "UanXKEafWxvXAayJjpsmZ4bFt7n6Xg4438WZXBiZKCPobLJAiHfe72n618kE6PCNU" + + "77cyU5Rk8J3CuY6QzZPzwuiXz2GLfkUMCYd9jGT6g53XbE6SwCsmGnd9NJkBAaJf5" + + "1FAYRURrhHnp79PAoHftEWtZEuU8MCPMdSRjzxYMRS4ScUzg5viDMTAkE8frsfCVZ" + + "hxsFwGUyNNno8eiqrrYmpbJGEwwK3S4437JboAUEFPdMNn8zNQWZcLLVrK9KyQeKM" + + "XpKkf4zJV6sZJ7gBMpzvPL18ULEgXTy7VsNBKmsfC1rM4WVG9ri1UixEcLDS79foC" + + "Jb3FnSr1T4MRKESeN3W" + response, err := d.ChannelImport(channelkey, nil) + if err != nil { + t.Error(err) + } + channels, err := d.ChannelList(nil, 1, 50, nil) + seen := false + for _, c := range channels.Items { + if c.Name == channelName { + seen = true + } + } + if !seen { + t.Error("couldn't find imported channel") + } + t.Log("Response:", *response) +} + +func TestClient_ChannelImportWithWalletID(t *testing.T) { + d := NewClient("") + + id := "lbry#wallet#id:" + fmt.Sprintf("%d", rand.Int()) + wallet, err := d.WalletCreate(id, nil) + + // A channel created just for automated testing purposes + channelName := "@LbryAutomatedTestChannel" + channelkey := "7943FWPBHZES4dUcMXSpDYwoM5a2tsyJT1R8V54QoUhekGcqmeH3hbzDXoLLQ8" + + "oKkfb99PgGK5efrZeYqaxg4X5XRJMJ6gKC8hqKcnwhYkmKDXmoBDNgd2ccZ9jhP8z" + + "HG3NJorAN9Hh4XMyBc5goBLZYYvC9MYvBmT3Fcteb5saqMvmQxFURv74NqXLQZC1t" + + "p6iRZKfTj77Pd5gsBsCYAbVmCqzbm5m1hHkUmfFEZVGcQNTYCDwZn543xSMYvSPnJ" + + "zt8tRYCJWaPdj713uENZZMo3gxuAMb1NwSnx8tbwETp7WPkpFLL6HZ9jKpB8BURHM" + + "F1RFD1PRyqbC6YezPyPQ2oninKKHdBduvXZG5KF2G2Q3ixsuE2ntifBBo1f5PotRk" + + "UanXKEafWxvXAayJjpsmZ4bFt7n6Xg4438WZXBiZKCPobLJAiHfe72n618kE6PCNU" + + "77cyU5Rk8J3CuY6QzZPzwuiXz2GLfkUMCYd9jGT6g53XbE6SwCsmGnd9NJkBAaJf5" + + "1FAYRURrhHnp79PAoHftEWtZEuU8MCPMdSRjzxYMRS4ScUzg5viDMTAkE8frsfCVZ" + + "hxsFwGUyNNno8eiqrrYmpbJGEwwK3S4437JboAUEFPdMNn8zNQWZcLLVrK9KyQeKM" + + "XpKkf4zJV6sZJ7gBMpzvPL18ULEgXTy7VsNBKmsfC1rM4WVG9ri1UixEcLDS79foC" + + "Jb3FnSr1T4MRKESeN3W" + response, err := d.ChannelImport(channelkey, &wallet.ID) + if err != nil { + t.Error(err) + } + channels, err := d.ChannelList(nil, 1, 50, &wallet.ID) + seen := false + for _, c := range channels.Items { + if c.Name == channelName { + seen = true + } + } + if !seen { + t.Error("couldn't find imported channel") + } + t.Log("Response:", *response) +} + +func TestClient_WalletCreate(t *testing.T) { + d := NewClient("") + + id := "lbry#wallet#id:" + fmt.Sprintf("%d", rand.Int()) + wallet, err := d.WalletCreate(id, nil) + if err != nil { + t.Fatal(err) + } + if wallet.ID != id { + prettyPrint(*wallet) + t.Fatalf("wallet ID mismatch, expected %q, got %q", id, wallet.Name) + } +} + +func TestClient_WalletCreateWithOpts(t *testing.T) { + d := NewClient("") + + id := "lbry#wallet#id:" + fmt.Sprintf("%d", rand.Int()) + wallet, err := d.WalletCreate(id, &WalletCreateOpts{CreateAccount: true, SingleKey: true}) + if err != nil { + t.Fatal(err) + } + accounts, err := d.AccountListForWallet(id) + if err != nil { + t.Fatal(err) + } + prettyPrint(wallet) + prettyPrint(accounts) + if accounts.LBCMainnet[0].Name == "" { + t.Fatalf("account name is empty") + } +} + +func TestClient_WalletList(t *testing.T) { + d := NewClient("") + + id := "lbry#wallet#id:" + fmt.Sprintf("%d", rand.Int()) + wList, err := d.WalletList(id) + if err == nil { + t.Fatalf("wallet %v was unexpectedly found", id) + } + if err.Error() != fmt.Sprintf("Error in daemon: Couldn't find wallet: %v.", id) { + t.Fatal(err) + } + + _, err = d.WalletCreate(id, &WalletCreateOpts{CreateAccount: true, SingleKey: true}) + if err != nil { + t.Fatal(err) + } + + wList, err = d.WalletList(id) + if err != nil { + t.Fatal(err) + } + if len(*wList) < 1 { + t.Fatal("wallet list is empty") + } + if (*wList)[0].ID != id { + t.Fatalf("wallet ID mismatch, expected %q, got %q", id, (*wList)[0].ID) + } +} + +func TestClient_WalletRemoveWalletAdd(t *testing.T) { + d := NewClient("") + + id := "lbry#wallet#id:" + fmt.Sprintf("%d", rand.Int()) + wallet, err := d.WalletCreate(id, nil) + if err != nil { + t.Fatal(err) + } + + _, err = d.WalletRemove(id) + if err != nil { + t.Fatal(err) + } + + addedWallet, err := d.WalletAdd(id) + if err != nil { + t.Fatal(err) + } + if addedWallet.ID != wallet.ID { + prettyPrint(*addedWallet) + t.Fatalf("wallet ID mismatch, expected %q, got %q", wallet.ID, addedWallet.Name) + } +} diff --git a/extras/jsonrpc/daemon_types.go b/extras/jsonrpc/daemon_types.go index 5246480..25c412f 100644 --- a/extras/jsonrpc/daemon_types.go +++ b/extras/jsonrpc/daemon_types.go @@ -271,7 +271,9 @@ type AddressListResponse []struct { Pubkey string `json:"pubkey"` UsedTimes uint64 `json:"used_times"` } + type ChannelExportResponse string +type ChannelImportResponse string type ChannelListResponse struct { Items []Transaction `json:"items"` @@ -538,3 +540,10 @@ type NumClaimsInChannelResponse map[string]struct { } type ClaimShowResponse *Claim + +type Wallet struct { + ID string `json:"id"` + Name string `json:"name"` +} + +type WalletList []Wallet diff --git a/go.mod b/go.mod index d10a72c..24f9491 100644 --- a/go.mod +++ b/go.mod @@ -1,50 +1,35 @@ -module github.com/lbryio/lbry.go +module github.com/lbryio/lbry.go/v2 require ( - github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf // indirect github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 github.com/davecgh/go-spew v1.1.1 github.com/fatih/structs v1.1.0 github.com/go-errors/errors v1.0.1 github.com/go-ini/ini v1.38.2 - github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect github.com/golang/protobuf v1.3.0 - github.com/google/go-cmp v0.2.0 // indirect - github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect - github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.6.2 github.com/gorilla/rpc v1.1.0 - github.com/gorilla/websocket v1.2.0 // indirect - github.com/jtolds/gls v4.2.1+incompatible // indirect + github.com/lbryio/lbry.go v1.1.2 github.com/lbryio/lbryschema.go v0.0.0-20190602173230-6d2f69a36f46 github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04 github.com/lbryio/types v0.0.0-20190422033210-321fb2abda9c - github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect - github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 // indirect github.com/lyoshenka/bencode v0.0.0-20180323155644-b7abd7672df5 github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 github.com/nlopes/slack v0.5.0 - github.com/pkg/errors v0.8.1 // indirect github.com/sebdah/goldie v0.0.0-20180424091453-8784dd1ab561 github.com/sergi/go-diff v1.0.0 github.com/shopspring/decimal v0.0.0-20180607144847-19e3cb6c2930 github.com/sirupsen/logrus v1.2.0 - github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect - github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c // indirect github.com/spf13/cast v1.2.0 github.com/stretchr/testify v1.3.0 github.com/uber-go/atomic v1.3.2 github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d - go.uber.org/atomic v1.3.2 // indirect golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a - golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect - golang.org/x/sys v0.0.0-20190520201301-c432e742b0af // indirect golang.org/x/time v0.0.0-20181108054448-85acf8d2951c - google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f // indirect google.golang.org/grpc v1.17.0 - gopkg.in/ini.v1 v1.41.0 // indirect gopkg.in/nullbio/null.v6 v6.0.0-20161116030900-40264a2e6b79 - gotest.tools v2.2.0+incompatible // indirect ) + +go 1.12 diff --git a/go.sum b/go.sum index 4524611..63904a7 100644 --- a/go.sum +++ b/go.sum @@ -66,6 +66,10 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfM github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/lbryio/errors.go v0.0.0-20180223142025-ad03d3cc6a5c/go.mod h1:muH7wpUqE8hRA3OrYYosw9+Sl681BF9cwcjzE+OCNK8= +github.com/lbryio/lbry.go v1.1.2 h1:Dyxc+glT/rVWJwHfIf7vjlPYYbjzrQz5ARmJd5Hp69c= +github.com/lbryio/lbry.go v1.1.2/go.mod h1:JtyI30bU51rm0LZ/po3mQuzf++14OWb6kR/6mMRAmKU= +github.com/lbryio/lbryschema.go v0.0.0-20190428231007-c54836bca002/go.mod h1:dAzPCBj3CKKWBGYBZxK6tKBP5SCgY2tqd9SnQd/OyKo= github.com/lbryio/lbryschema.go v0.0.0-20190602173230-6d2f69a36f46 h1:LemfR+rMxhf7nnOrzy2HqS7Me7SZ5gEwOcNFzKC8ySQ= github.com/lbryio/lbryschema.go v0.0.0-20190602173230-6d2f69a36f46/go.mod h1:dAzPCBj3CKKWBGYBZxK6tKBP5SCgY2tqd9SnQd/OyKo= github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04 h1:Nze+C2HbeKvhjI/kVn+9Poj/UuEW5sOQxcsxqO7L3GI=