add accountAdd support
refactor account management
This commit is contained in:
parent
c36c67961f
commit
85e34cb335
3 changed files with 119 additions and 24 deletions
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
Loading…
Reference in a new issue