add accountAdd support

refactor account management
This commit is contained in:
Niko Storni 2019-09-24 20:35:04 +02:00
parent c36c67961f
commit 85e34cb335
3 changed files with 119 additions and 24 deletions

View file

@ -1,8 +1,10 @@
package jsonrpc package jsonrpc
import ( import (
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"reflect" "reflect"
"sort" "sort"
@ -11,6 +13,7 @@ import (
"time" "time"
"github.com/lbryio/lbry.go/extras/errors" "github.com/lbryio/lbry.go/extras/errors"
"github.com/lbryio/lbry.go/stream"
"github.com/fatih/structs" "github.com/fatih/structs"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
@ -190,16 +193,16 @@ func (d *Client) AccountFund(fromAccount string, toAccount string, amount string
}) })
} }
func (d *Client) AccountCreate(accountName string, singleKey bool) (*AccountCreateResponse, error) { func (d *Client) AccountCreate(accountName string, singleKey bool) (*Account, error) {
response := new(AccountCreateResponse) response := new(Account)
return response, d.call(response, "account_create", map[string]interface{}{ return response, d.call(response, "account_create", map[string]interface{}{
"account_name": accountName, "account_name": accountName,
"single_key": singleKey, "single_key": singleKey,
}) })
} }
func (d *Client) AccountRemove(accountID string) (*AccountRemoveResponse, error) { func (d *Client) AccountRemove(accountID string) (*Account, error) {
response := new(AccountRemoveResponse) response := new(Account)
return response, d.call(response, "account_remove", map[string]interface{}{ return response, d.call(response, "account_remove", map[string]interface{}{
"account_id": accountID, "account_id": accountID,
}) })
@ -574,3 +577,80 @@ func (d *Client) SupportAbandon(claimID *string, txid *string, nout *uint, keep
structs.DefaultTagName = "json" structs.DefaultTagName = "json"
return response, d.call(response, "support_abandon", structs.Map(args)) return response, d.call(response, "support_abandon", structs.Map(args))
} }
func (d *Client) AccountAdd(accountName string, seed *string, privateKey *string, publicKey *string, singleKey *bool, walletID *string) (*Account, error) {
response := new(Account)
args := struct {
AccountName string `json:"account_name"`
Seed *string `json:"seed,omitempty"`
PrivateKey *string `json:"private_key,omitempty"`
PublicKey *string `json:"public_key,omitempty"`
SingleKey *bool `json:"single_key,omitempty"`
WalletID *string `json:"wallet_id,omitempty"`
}{
AccountName: accountName,
Seed: seed,
PrivateKey: privateKey,
PublicKey: publicKey,
SingleKey: singleKey,
WalletID: walletID,
}
structs.DefaultTagName = "json"
return response, d.call(response, "account_add", structs.Map(args))
}
// GetStreamSizeByMagic uses "magic" to not just estimate, but actually return the exact size of a stream
// It does so by fetching the sd blob and the last blob from our S3 bucket, decrypting and unpadding the last blob
// adding up all full blobs that have a known size and finally adding the real last blob size too.
// This will only work if we host at least the sd blob and the last blob on S3, if not, this will error.
func (c *Claim) GetStreamSizeByMagic() (streamSize uint64, e error) {
if c.Value.GetStream() == nil {
return 0, errors.Err("this claim is not a stream")
}
resp, err := http.Get(reflectorURL + hex.EncodeToString(c.Value.GetStream().Source.SdHash))
if err != nil {
return 0, errors.Err(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return 0, errors.Err(err)
}
sdb := &stream.SDBlob{}
err = sdb.UnmarshalJSON(body)
if err != nil {
return 0, err
}
lastBlobIndex := len(sdb.BlobInfos) - 2
lastBlobHash := sdb.BlobInfos[lastBlobIndex].BlobHash
if len(sdb.BlobInfos) > 2 {
streamSize = uint64(stream.MaxBlobSize-1) * uint64(len(sdb.BlobInfos)-2)
}
resp2, err := http.Get(reflectorURL + hex.EncodeToString(lastBlobHash))
if err != nil {
return 0, errors.Err(err)
}
defer resp2.Body.Close()
body2, err := ioutil.ReadAll(resp2.Body)
if err != nil {
return 0, errors.Err(err)
}
defer func() {
if r := recover(); r != nil {
e = errors.Err("recovered from DecryptBlob panic for blob %s", lastBlobHash)
}
}()
lastBlob, err := stream.DecryptBlob(body2, sdb.Key, sdb.BlobInfos[lastBlobIndex].IV)
if err != nil {
return 0, errors.Err(err)
}
streamSize += uint64(len(lastBlob))
return streamSize, nil
}

View file

@ -445,6 +445,26 @@ func TestClient_AccountCreate(t *testing.T) {
prettyPrint(*account) prettyPrint(*account)
} }
func TestClient_AccountAdd(t *testing.T) {
d := NewClient("")
name := "test" + fmt.Sprintf("%d", time.Now().Unix()) + "@lbry.com"
pubKey := "tpubDA9GDAntyJu4hD3wU7175p7CuV6DWbYXfyb2HedBA3yuBp9HZ4n3QE4Ex6RHCSiEuVp2nKAL1Lzf2ZLo9ApaFgNaJjG6Xo1wB3iEeVbrDZp"
account, err := d.AccountAdd(name, nil, nil, &pubKey, util.PtrToBool(true), nil)
if err != nil {
t.Fatal(err)
return
}
if account.Name != name {
t.Errorf("account name mismatch, expected %q, got %q", name, account.Name)
return
}
if account.PublicKey != pubKey {
t.Errorf("public key mismatch, expected %q, got %q", name, account.Name)
return
}
prettyPrint(*account)
}
func TestClient_AccountRemove(t *testing.T) { func TestClient_AccountRemove(t *testing.T) {
d := NewClient("") d := NewClient("")
createdAccount, err := d.AccountCreate("test"+fmt.Sprintf("%d", time.Now().Unix())+"@lbry.com", false) createdAccount, err := d.AccountCreate("test"+fmt.Sprintf("%d", time.Now().Unix())+"@lbry.com", false)

View file

@ -204,14 +204,21 @@ type Account struct {
MaximumUsesPerAddress uint64 `json:"maximum_uses_per_address"` MaximumUsesPerAddress uint64 `json:"maximum_uses_per_address"`
} `json:"receiving"` } `json:"receiving"`
} `json:"address_generator"` } `json:"address_generator"`
Certificates uint64 `json:"certificates"` Certificates uint64 `json:"certificates"`
Coins float64 `json:"coins"` Coins float64 `json:"coins"`
Encrypted bool `json:"encrypted"` Encrypted bool `json:"encrypted"`
ID string `json:"id"` ID string `json:"id"`
IsDefault bool `json:"is_default"` IsDefault bool `json:"is_default"`
Name string `json:"name"` Ledger *string `json:"ledger,omitempty"`
PublicKey string `json:"public_key"` ModifiedOn *float64 `json:"modified_on,omitempty"`
Satoshis uint64 `json:"satoshis"` Name string `json:"name"`
Preferences *struct {
Theme string `json:"theme"`
} `json:"preferences,omitempty"`
PublicKey string `json:"public_key"`
PrivateKey *string `json:"private_key,omitempty"`
Seed *string `json:"seed,omitempty"`
Satoshis uint64 `json:"satoshis"`
} }
type AccountListResponse struct { type AccountListResponse struct {
@ -227,18 +234,6 @@ type AccountBalanceResponse struct {
Total decimal.Decimal `json:"total"` Total decimal.Decimal `json:"total"`
} }
type AccountCreateResponse struct {
ID string `json:"id"`
Name string `json:"name"`
PublicKey string `json:"public_key"`
PrivateKey string `json:"private_key"`
Seed string `json:"seed"`
Ledger string `json:"ledger"`
ModifiedOn float64 `json:"modified_on"`
}
type AccountRemoveResponse AccountCreateResponse
type Transaction struct { type Transaction struct {
Address string `json:"address"` Address string `json:"address"`
Amount string `json:"amount"` Amount string `json:"amount"`