Add wallet commands to JSON-RPC client #73

Merged
anbsky merged 8 commits from feature/wallet into master 2019-10-08 08:08:57 +02:00
5 changed files with 245 additions and 30 deletions

View file

@ -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) {
nikooo777 commented 2019-09-25 16:18:04 +02:00 (Migrated from github.com)
Review

i think we should just add an optional param to the current account functions. just like I did for AccountAdd yesterday

i think we should just add an optional param to the current account functions. just like I did for AccountAdd yesterday
anbsky commented 2019-09-25 18:44:58 +02:00 (Migrated from github.com)
Review

That's how we ended up with v2 of lbry.go already — introducing backwards incompatible changes way too liberally. I don't think we should do that.

P.S. That's another example where opts would make things easier by not breaking backwards compatibility.

That's how we ended up with v2 of lbry.go already — introducing backwards incompatible changes way too liberally. I don't think we should do that. P.S. That's another example where opts would make things easier by not breaking backwards compatibility.
nikooo777 commented 2019-09-30 16:04:40 +02:00 (Migrated from github.com)
Review

I think we shouldn't worry too much about backward compatibility. If one doesn't want to stay up to date with lbry.go/sdk then they can lock themselves into a commit that supports such old versions.
We don't have the time to support multiple versions, only the current one. I still feel like it should not be split out and rather updated

I think we shouldn't worry too much about backward compatibility. If one doesn't want to stay up to date with lbry.go/sdk then they can lock themselves into a commit that supports such old versions. We don't have the time to support multiple versions, only the current one. I still feel like it should not be split out and rather updated
anbsky commented 2019-10-03 20:28:31 +02:00 (Migrated from github.com)
Review

I spent a few minutes adding a nil parameter to AccoutList in calls around the test code that don't know about wallet_id and it felt quite ugly to me. Barring all the uncertainties of designing an API ahead of client code, I'd hazard a guess the majority of clients will be requiring the argument-less version of account_list and we should keep it that.

I spent a few minutes adding a `nil` parameter to `AccoutList` in calls around the test code that don't know about `wallet_id` and it felt quite ugly to me. Barring all the uncertainties of designing an API ahead of client code, I'd hazard a guess the majority of clients will be requiring the argument-less version of `account_list` and we should keep it that.
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,
})
}
@ -518,6 +525,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{}{
@ -595,3 +610,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})
}

View file

@ -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
@ -432,7 +442,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)
@ -467,7 +477,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
@ -487,9 +498,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)
@ -506,3 +515,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)
nikooo777 commented 2019-10-03 18:28:53 +02:00 (Migrated from github.com)
Review

you should try calling an extra one without walletID to see if it holds up or not

you should try calling an extra one without walletID to see if it holds up or not
}
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)
}
}

View file

@ -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

23
go.mod
View file

@ -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
nikooo777 commented 2019-10-03 18:22:49 +02:00 (Migrated from github.com)
Review

something must be still using the wrong stuff

something must be still using the wrong stuff
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

4
go.sum
View file

@ -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=
nikooo777 commented 2019-10-03 18:23:38 +02:00 (Migrated from github.com)
Review

nope, we have to use lbry.go for this I think

nope, we have to use lbry.go for this I think
anbsky commented 2019-10-03 19:35:39 +02:00 (Migrated from github.com)
Review

Strange since this is not a manual edit

Strange since this is not a manual edit
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=