Merge pull request #50 from lbryio/lbrynet-updates

lbrynet SDK updates (support for lbrynet 0.37.*)
This commit is contained in:
Niko 2019-05-10 14:16:28 +02:00 committed by GitHub
commit abb34bf2dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1026 additions and 539 deletions

View file

@ -6,7 +6,10 @@ go:
env:
- GO111MODULE=on
global:
- GO111MODULE=on
#GITHUB_TOKEN
secure: "P4YMfllsq/guf5swmBl80IHGvNfUM+5X2b+0LvQQxGJpY9TD6d+PW6U1C90HIT0CDk6UZbtlHyGN+oo+shsWnwMIaM4qmbGdRgtG4TZolXY1QtYQZFW9fTWeHM0wnJeXLV8V4vpTRHnkLrvT8PctbGp5pVOEtcV4y3sEnMP1rkxnMPeHtrDbTlpBmBYEziByEpbg3pe3CE9xVaDD9DqgW7VOOZnQQl7exTtjsIeJYI7OYvdidf/04p632/8WZP2EJbmA2HunfTydWtcD51lCF8V3IvhKKqH4/7sNOKfmUwTDyhLltk9eDcFsYR/FYsy8njH4QDBBrKo/bPq3jzgKF9BY7g28/jMTDY4vDY0Na+4a3+7sDqwdsZ+eiZrgWYUbZ4MwYtpUtcvp8gUz7Avs3v7BBgYsYpgLEW47bT6uNLGO+SdfSwBCYuxT5P0IGCv6wkgYcYgfqVafk+9FiwJlayP2j3wPOdauiYh4WnYX1Rt0zNvaiP5iBhkXwIv3VvUcI1Yu9k0eLDibzZlpR8fkGw3USl+omdjCvXDfJQW1ghMONTm0d7VPG84P/MRhJ+thoh1UwMaT3S0sdPznRnNL6XDntCRT1CZW4l0jfyCPDBW2qw8dWunULYsQZTPWnv4s+BuRRDsfGjyamH5b8evh0TOF+XNOFewmNvflWBNG2y0="
install: true
script:
@ -16,3 +19,12 @@ script:
notifications:
email: false
deploy:
provider: script
skip_cleanup: true
script: ./scripts/deploy.sh
file: bin/ytsync
on:
repo: lbryio/ytsync
tags: true

View file

@ -3,7 +3,7 @@ package claim
import (
"bytes"
types "github.com/lbryio/types/v1/go"
types "github.com/lbryio/types/v2/go"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"

View file

@ -10,6 +10,8 @@ import (
"strings"
"time"
"github.com/fatih/structs"
"github.com/lbryio/lbry.go/extras/errors"
"github.com/mitchellh/mapstructure"
@ -41,7 +43,7 @@ func NewClient(address string) *Client {
func NewClientAndWait(address string) *Client {
d := NewClient(address)
for {
_, err := d.WalletBalance()
_, err := d.AccountBalance(nil)
if err == nil {
return d
}
@ -49,7 +51,7 @@ func NewClientAndWait(address string) *Client {
}
}
func decode(data interface{}, targetStruct interface{}) error {
func Decode(data interface{}, targetStruct interface{}) error {
config := &mapstructure.DecoderConfig{
Metadata: nil,
Result: targetStruct,
@ -125,7 +127,7 @@ func (d *Client) call(response interface{}, command string, params map[string]in
if err != nil {
return err
}
return decode(result, response)
return Decode(result, response)
}
func (d *Client) SetRPCTimeout(timeout time.Duration) {
@ -134,9 +136,269 @@ func (d *Client) SetRPCTimeout(timeout time.Duration) {
})
}
func (d *Client) Commands() (*CommandsResponse, error) {
response := new(CommandsResponse)
return response, d.call(response, "commands", map[string]interface{}{})
//============================================
// NEW SDK
//============================================
func (d *Client) AccountList() (*AccountListResponse, error) {
response := new(AccountListResponse)
return response, d.call(response, "account_list", map[string]interface{}{})
}
type AccountSettings struct {
Default bool `json:"default"`
NewName string `json:"new_name"`
ReceivingGap int `json:"receiving_gap"`
ReceivingMaxUses int `json:"receiving_max_uses"`
ChangeGap int `json:"change_gap"`
ChangeMaxUses int `json:"change_max_uses"`
}
func (d *Client) AccountSet(accountID string, settings AccountSettings) (*Account, error) {
response := new(Account)
return response, d.call(response, "account_list", map[string]interface{}{})
}
func (d *Client) AccountBalance(account *string) (*AccountBalanceResponse, error) {
response := new(AccountBalanceResponse)
return response, d.call(response, "account_balance", map[string]interface{}{
"account_id": account,
})
}
func (d *Client) AccountFund(fromAccount string, toAccount string, amount string, outputs uint64) (*AccountFundResponse, error) {
response := new(AccountFundResponse)
return response, d.call(response, "account_fund", map[string]interface{}{
"from_account": fromAccount,
"to_account": toAccount,
"amount": amount,
"outputs": outputs,
"broadcast": true,
})
}
func (d *Client) AccountCreate(accountName string, singleKey bool) (*AccountCreateResponse, error) {
response := new(AccountCreateResponse)
return response, d.call(response, "account_create", map[string]interface{}{
"account_name": accountName,
"single_key": singleKey,
})
}
func (d *Client) AddressUnused(account *string) (*AddressUnusedResponse, error) {
response := new(AddressUnusedResponse)
return response, d.call(response, "address_unused", map[string]interface{}{
"account_id": account,
})
}
func (d *Client) ChannelList(account *string, page uint64, pageSize uint64) (*ChannelListResponse, error) {
if page == 0 {
return nil, errors.Err("pages start from 1")
}
response := new(ChannelListResponse)
return response, d.call(response, "channel_list", map[string]interface{}{
"account_id": account,
"page": page,
"page_size": pageSize,
"include_protobuf": true,
})
}
type streamType string
var (
StreamTypeVideo = streamType("video")
StreamTypeAudio = streamType("audio")
StreamTypeImage = streamType("image")
)
type Location struct {
Country *string `json:"country,omitempty"`
State *string `json:"state,omitempty"`
City *string `json:"city,omitempty"`
PostalCode *string `json:"code,omitempty"`
Latitude *string `json:"latitude,omitempty"`
Longitude *string `json:"longitude,omitempty"`
}
type ClaimCreateOptions struct {
Title string `json:"title"`
Description string `json:"description"`
Tags []string `json:"tags,omitempty"`
Languages []string `json:"languages,omitempty"`
Locations []Location `json:"locations,omitempty"`
ThumbnailURL *string `json:"thumbnail_url,omitempty"`
AccountID *string `json:"account_id,omitempty"`
ClaimAddress *string `json:"claim_address,omitempty"`
Preview *bool `json:"preview,omitempty"`
}
type ChannelCreateOptions struct {
ClaimCreateOptions `json:",flatten"`
Email *string `json:"email,omitempty"`
WebsiteURL *string `json:"website_url,omitempty"`
CoverURL *string `json:"cover_url,omitempty"`
Featured []string `json:"featured,omitempty"`
}
func (d *Client) ChannelCreate(name string, bid float64, options ChannelCreateOptions) (*TransactionSummary, error) {
response := new(TransactionSummary)
args := struct {
Name string `json:"name"`
Bid string `json:"bid"`
FilePath string `json:"file_path,omitempty"`
IncludeProtoBuf bool `json:"include_protobuf"`
ChannelCreateOptions `json:",flatten"`
}{
Name: name,
Bid: fmt.Sprintf("%.6f", bid),
IncludeProtoBuf: true,
ChannelCreateOptions: options,
}
structs.DefaultTagName = "json"
return response, d.call(response, "channel_create", structs.Map(args))
}
type ChannelUpdateOptions struct {
ChannelCreateOptions `json:",flatten"`
NewSigningKey *bool `json:"new_signing_key,omitempty"`
ClearFeatured *bool `json:"clear_featured,omitempty"`
ClearTags *bool `json:"clear_tags,omitempty"`
ClearLanguages *bool `json:"clear_languages,omitempty"`
ClearLocations *bool `json:"clear_locations,omitempty"`
}
func (d *Client) ChannelUpdate(claimID string, options ChannelUpdateOptions) (*TransactionSummary, error) {
response := new(TransactionSummary)
args := struct {
ClaimID string `json:"claim_id"`
IncludeProtoBuf bool `json:"include_protobuf"`
*ChannelUpdateOptions `json:",flatten"`
}{
ClaimID: claimID,
IncludeProtoBuf: true,
ChannelUpdateOptions: &options,
}
structs.DefaultTagName = "json"
return response, d.call(response, "channel_update", structs.Map(args))
}
type StreamCreateOptions struct {
ClaimCreateOptions `json:",flatten"`
Fee *Fee `json:",omitempty,flatten"`
Author *string `json:"author,omitempty"`
License *string `json:"license,omitempty"`
LicenseURL *string `json:"license_url,omitempty"`
StreamType *streamType `json:"stream_type,omitempty"`
ReleaseTime *int64 `json:"release_time,omitempty"`
Duration *uint64 `json:"duration,omitempty"`
ImageWidth *uint `json:"image_width,omitempty"`
ImageHeight *uint `json:"image_height,omitempty"`
VideoWidth *uint `json:"video_width,omitempty"`
VideoHeight *uint `json:"video_height,omitempty"`
Preview *string `json:"preview,omitempty"`
AllowDuplicateName *bool `json:"allow_duplicate_name,omitempty"`
ChannelName *string `json:"channel_name,omitempty"`
ChannelID *string `json:"channel_id,omitempty"`
ChannelAccountID *string `json:"channel_account_id,omitempty"`
}
func (d *Client) StreamCreate(name, filePath string, bid float64, options StreamCreateOptions) (*TransactionSummary, error) {
response := new(TransactionSummary)
args := struct {
Name string `json:"name"`
Bid string `json:"bid"`
FilePath string `json:"file_path,omitempty"`
FileSize *string `json:"file_size,omitempty"`
IncludeProtoBuf bool `json:"include_protobuf"`
*StreamCreateOptions `json:",flatten"`
}{
Name: name,
FilePath: filePath,
Bid: fmt.Sprintf("%.6f", bid),
IncludeProtoBuf: true,
StreamCreateOptions: &options,
}
structs.DefaultTagName = "json"
return response, d.call(response, "stream_create", structs.Map(args))
}
func (d *Client) StreamAbandon(txID string, nOut uint64, accountID *string, blocking bool) (*ClaimAbandonResponse, error) {
response := new(ClaimAbandonResponse)
err := d.call(response, "claim_abandon", map[string]interface{}{
"txid": txID,
"nout": nOut,
"account_id": accountID,
"include_protobuf": true,
})
if err != nil {
return nil, err
}
return response, nil
}
type StreamUpdateOptions struct {
ClearTags *bool `json:"clear_tags,omitempty"`
ClearLanguages *bool `json:"clear_languages,omitempty"`
ClearLocations *bool `json:"clear_locations,omitempty"`
Name *string `json:"name,omitempty"`
FilePath *string `json:"file_path,omitempty"`
FileSize *uint64 `json:"file_size,omitempty"`
Bid *string `json:"bid,omitempty"`
*StreamCreateOptions `json:",flatten"`
}
func (d *Client) StreamUpdate(claimID string, options StreamUpdateOptions) (*TransactionSummary, error) {
response := new(TransactionSummary)
args := struct {
ClaimID string `json:"claim_id"`
IncludeProtoBuf bool `json:"include_protobuf"`
*StreamUpdateOptions `json:",flatten"`
}{
ClaimID: claimID,
IncludeProtoBuf: true,
StreamUpdateOptions: &options,
}
structs.DefaultTagName = "json"
return response, d.call(response, "stream_update", structs.Map(args))
}
func (d *Client) ChannelAbandon(txID string, nOut uint64, accountID *string, blocking bool) (*ClaimAbandonResponse, error) {
response := new(ClaimAbandonResponse)
err := d.call(response, "claim_abandon", map[string]interface{}{
"txid": txID,
"nout": nOut,
"account_id": accountID,
"include_protobuf": true,
})
if err != nil {
return nil, err
}
return response, nil
}
func (d *Client) AddressList(account *string) (*AddressListResponse, error) {
response := new(AddressListResponse)
return response, d.call(response, "address_list", map[string]interface{}{
"account_id": account,
})
}
func (d *Client) ClaimList(account *string, page uint64, pageSize uint64) (*ClaimListResponse, error) {
if page == 0 {
return nil, errors.Err("pages start from 1")
}
response := new(ClaimListResponse)
err := d.call(response, "claim_list", map[string]interface{}{
"account_id": account,
"page": page,
"page_size": pageSize,
"include_protobuf": true,
})
if err != nil {
return nil, err
}
return response, nil
}
func (d *Client) Status() (*StatusResponse, error) {
@ -144,29 +406,26 @@ func (d *Client) Status() (*StatusResponse, error) {
return response, d.call(response, "status", map[string]interface{}{})
}
func (d *Client) WalletBalance() (*WalletBalanceResponse, error) {
rawResponse, err := d.callNoDecode("wallet_balance", map[string]interface{}{})
if err != nil {
return nil, err
}
dec, err := decodeNumber(rawResponse)
if err != nil {
return nil, err
}
response := WalletBalanceResponse(dec)
return &response, nil
}
func (d *Client) WalletList() (*WalletListResponse, error) {
response := new(WalletListResponse)
return response, d.call(response, "wallet_list", map[string]interface{}{})
}
func (d *Client) UTXOList() (*UTXOListResponse, error) {
func (d *Client) UTXOList(account *string) (*UTXOListResponse, error) {
response := new(UTXOListResponse)
return response, d.call(response, "utxo_list", map[string]interface{}{})
return response, d.call(response, "utxo_list", map[string]interface{}{
"account_id": account,
})
}
func (d *Client) Get(uri string) (*GetResponse, error) {
response := new(GetResponse)
return response, d.call(response, "get", map[string]interface{}{
"uri": uri,
"include_protobuf": true,
})
}
func (d *Client) FileList() (*FileListResponse, error) {
response := new(FileListResponse)
return response, d.call(response, "file_list", map[string]interface{}{
"include_protobuf": true,
})
}
func (d *Client) Version() (*VersionResponse, error) {
@ -174,269 +433,20 @@ func (d *Client) Version() (*VersionResponse, error) {
return response, d.call(response, "version", map[string]interface{}{})
}
func (d *Client) Get(url string, filename *string, timeout *uint) (*GetResponse, error) {
response := new(GetResponse)
return response, d.call(response, "get", map[string]interface{}{
"uri": url,
"file_name": filename,
"timeout": timeout,
})
}
func (d *Client) ClaimList(name string) (*ClaimListResponse, error) {
response := new(ClaimListResponse)
return response, d.call(response, "claim_list", map[string]interface{}{
"name": name,
})
}
func (d *Client) ClaimShow(claimID *string, txid *string, nout *uint) (*ClaimShowResponse, error) {
response := new(ClaimShowResponse)
return response, d.call(response, "claim_show", map[string]interface{}{
"claim_id": claimID,
"txid": txid,
"nout": nout,
})
}
func (d *Client) PeerList(blobHash string, timeout *uint) (*PeerListResponse, error) {
rawResponse, err := d.callNoDecode("peer_list", map[string]interface{}{
"blob_hash": blobHash,
"timeout": timeout,
})
if err != nil {
return nil, err
}
castResponse, ok := rawResponse.([]interface{})
if !ok {
return nil, errors.Err("invalid peer_list response")
}
peers := []PeerListResponsePeer{}
for _, peer := range castResponse {
t, ok := peer.(map[string]interface{})
if !ok {
return nil, errors.Err("invalid peer_list response")
}
if len(t) != 3 {
return nil, errors.Err("invalid triplet in peer_list response")
}
ip, ok := t["host"].(string)
if !ok {
return nil, errors.Err("invalid ip in peer_list response")
}
port, ok := t["port"].(json.Number)
if !ok {
return nil, errors.Err("invalid port in peer_list response")
}
nodeid, ok := t["node_id"].(string)
if !ok {
return nil, errors.Err("invalid nodeid in peer_list response")
}
portNum, err := port.Int64()
if err != nil {
return nil, errors.Wrap(err, 0)
} else if portNum < 0 {
return nil, errors.Err("invalid port in peer_list response")
}
peers = append(peers, PeerListResponsePeer{
IP: ip,
Port: uint(portNum),
NodeId: nodeid,
})
}
response := PeerListResponse(peers)
return &response, nil
}
func (d *Client) BlobGet(blobHash string, encoding *string, timeout *uint) (*BlobGetResponse, error) {
rawResponse, err := d.callNoDecode("blob_get", map[string]interface{}{
"blob_hash": blobHash,
"timeout": timeout,
"encoding": encoding,
})
if err != nil {
return nil, err
}
if _, ok := rawResponse.(string); ok {
return nil, nil // blob was downloaded, nothing to return
}
response := new(BlobGetResponse)
return response, decode(rawResponse, response)
}
func (d *Client) StreamAvailability(url string, search_timeout *uint64, blob_timeout *uint64) (*StreamAvailabilityResponse, error) {
response := new(StreamAvailabilityResponse)
return response, d.call(response, "stream_availability", map[string]interface{}{
"uri": url,
"search_timeout": search_timeout,
"blob_timeout": blob_timeout,
})
}
func (d *Client) StreamCostEstimate(url string, size *uint64) (*StreamCostEstimateResponse, error) {
rawResponse, err := d.callNoDecode("stream_cost_estimate", map[string]interface{}{
"uri": url,
"size": size,
})
if err != nil {
return nil, err
}
dec, err := decodeNumber(rawResponse)
if err != nil {
return nil, err
}
response := StreamCostEstimateResponse(dec)
return &response, nil
}
type FileListOptions struct {
SDHash *string
StreamHash *string
FileName *string
ClaimID *string
Outpoint *string
RowID *string
Name *string
}
func (d *Client) FileList(options FileListOptions) (*FileListResponse, error) {
response := new(FileListResponse)
return response, d.call(response, "file_list", map[string]interface{}{
"sd_hash": options.SDHash,
"stream_hash": options.StreamHash,
"file_name": options.FileName,
"claim_id": options.ClaimID,
"outpoint": options.Outpoint,
"rowid": options.RowID,
"name": options.Name,
})
}
func (d *Client) Resolve(url string) (*ResolveResponse, error) {
func (d *Client) Resolve(urls string) (*ResolveResponse, error) {
response := new(ResolveResponse)
return response, d.call(response, "resolve", map[string]interface{}{
"uri": url,
"urls": urls,
"include_protobuf": true,
})
}
func (d *Client) ChannelNew(name string, amount float64) (*ChannelNewResponse, error) {
response := new(ChannelNewResponse)
return response, d.call(response, "channel_new", map[string]interface{}{
"channel_name": name,
"amount": amount,
})
}
func (d *Client) ChannelList() (*ChannelListResponse, error) {
response := new(ChannelListResponse)
return response, d.call(response, "channel_list", map[string]interface{}{})
}
type PublishOptions struct {
Fee *Fee
Title *string
Description *string
Author *string
Language *string
License *string
LicenseURL *string
Thumbnail *string
Preview *string
NSFW *bool
ChannelName *string
ChannelID *string
ClaimAddress *string
ChangeAddress *string
}
func (d *Client) Publish(name, filePath string, bid float64, options PublishOptions) (*PublishResponse, error) {
response := new(PublishResponse)
return response, d.call(response, "publish", map[string]interface{}{
"name": name,
"file_path": filePath,
"bid": bid,
"fee": options.Fee,
"title": options.Title,
"description": options.Description,
"author": options.Author,
"language": options.Language,
"license": options.License,
"license_url": options.LicenseURL,
"thumbnail": options.Thumbnail,
"preview": options.Preview,
"nsfw": options.NSFW,
"channel_name": options.ChannelName,
"channel_id": options.ChannelID,
"claim_address": options.ClaimAddress,
"change_address": options.ChangeAddress,
})
}
func (d *Client) BlobAnnounce(blobHash, sdHash, streamHash *string) (*BlobAnnounceResponse, error) {
response := new(BlobAnnounceResponse)
return response, d.call(response, "blob_announce", map[string]interface{}{
"blob_hash": blobHash,
"stream_hash": streamHash,
"sd_hash": sdHash,
})
}
func (d *Client) WalletPrefillAddresses(numAddresses int, amount decimal.Decimal, broadcast bool) (*WalletPrefillAddressesResponse, error) {
if numAddresses < 1 {
return nil, errors.Err("must create at least 1 address")
}
response := new(WalletPrefillAddressesResponse)
return response, d.call(response, "wallet_prefill_addresses", map[string]interface{}{
"num_addresses": numAddresses,
"amount": amount,
"no_broadcast": !broadcast,
})
}
func (d *Client) WalletNewAddress() (*WalletNewAddressResponse, error) {
rawResponse, err := d.callNoDecode("wallet_new_address", map[string]interface{}{})
if err != nil {
return nil, err
}
address, ok := rawResponse.(string)
if !ok {
return nil, errors.Err("unexpected response")
}
response := WalletNewAddressResponse(address)
return &response, nil
}
func (d *Client) WalletUnusedAddress() (*WalletUnusedAddressResponse, error) {
rawResponse, err := d.callNoDecode("wallet_unused_address", map[string]interface{}{})
if err != nil {
return nil, err
}
address, ok := rawResponse.(string)
if !ok {
return nil, errors.Err("unexpected response")
}
response := WalletUnusedAddressResponse(address)
return &response, nil
}
func (d *Client) NumClaimsInChannel(url string) (uint64, error) {
/*
// use resolve?
func (d *Client) NumClaimsInChannel(channelClaimID string) (uint64, error) {
response := new(NumClaimsInChannelResponse)
err := d.call(response, "claim_list_by_channel", map[string]interface{}{
"uri": url,
err := d.call(response, "claim_search", map[string]interface{}{
"channel_id": channelClaimID,
})
if err != nil {
return 0, err
@ -444,42 +454,25 @@ func (d *Client) NumClaimsInChannel(url string) (uint64, error) {
return 0, errors.Err("no response")
}
channel, ok := (*response)[url]
channel, ok := (*response)[uri]
if !ok {
return 0, errors.Err("url not in response")
}
if channel.Error != "" {
if strings.Contains(channel.Error, "cannot be resolved") {
if channel.Error != nil {
if strings.Contains(*channel.Error, "cannot be resolved") {
return 0, nil
}
return 0, errors.Err(channel.Error)
return 0, errors.Err(*channel.Error)
}
return channel.ClaimsInChannel, nil
return *channel.ClaimsInChannel, nil
}
func (d *Client) ClaimListMine() (*ClaimListMineResponse, error) {
response := new(ClaimListMineResponse)
err := d.call(response, "claim_list_mine", map[string]interface{}{})
if err != nil {
return nil, err
} else if response == nil {
return nil, errors.Err("no response")
}
return response, nil
}
func (d *Client) ClaimAbandon(txID string, nOut int) (*ClaimAbandonResponse, error) {
response := new(ClaimAbandonResponse)
err := d.call(response, "claim_abandon", map[string]interface{}{
"txid": txID,
"nout": nOut,
*/
func (d *Client) ClaimSearch(claimName, claimID, txid *string, nout *uint) (*ClaimSearchResponse, error) {
response := new(ClaimSearchResponse)
return response, d.call(response, "claim_search", map[string]interface{}{
"claim_id": claimID,
"txid": txid,
"nout": nout,
"name": claimName,
})
if err != nil {
return nil, err
} else if response == nil {
return nil, errors.Err("no response")
}
return response, nil
}

View file

@ -1,8 +1,319 @@
package jsonrpc
import (
"encoding/json"
"fmt"
"strconv"
"testing"
"time"
"github.com/shopspring/decimal"
"github.com/lbryio/lbry.go/extras/util"
)
func TestStatus(t *testing.T) {
func prettyPrint(i interface{}) {
s, _ := json.MarshalIndent(i, "", "\t")
fmt.Println(string(s))
}
func TestClient_AccountFund(t *testing.T) {
d := NewClient("")
accounts, err := d.AccountList()
if err != nil {
t.Error(err)
}
account := (accounts.LBCRegtest)[0].ID
balanceString, err := d.AccountBalance(&account)
if err != nil {
t.Error(err)
}
balance, err := strconv.ParseFloat(string(*balanceString), 64)
if err != nil {
t.Error(err)
}
got, err := d.AccountFund(account, account, fmt.Sprintf("%f", balance/2.0), 40)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_AccountList(t *testing.T) {
d := NewClient("")
got, err := d.AccountList()
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_AccountBalance(t *testing.T) {
d := NewClient("")
got, err := d.AccountBalance(nil)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_AddressUnused(t *testing.T) {
d := NewClient("")
got, err := d.AddressUnused(nil)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_ChannelList(t *testing.T) {
d := NewClient("")
got, err := d.ChannelList(nil, 1, 50)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_StreamCreate(t *testing.T) {
d := NewClient("")
addressResponse, err := d.AddressUnused(nil)
if err != nil {
t.Error(err)
}
address := string(*addressResponse)
got, err := d.StreamCreate("test"+fmt.Sprintf("%d", time.Now().Unix()), "/home/niko/work2/2019-04-11_17-36-25-925698088.png", 14.37, StreamCreateOptions{
ClaimCreateOptions: ClaimCreateOptions{
Title: "This is a Test Title" + fmt.Sprintf("%d", time.Now().Unix()),
Description: "My Special Description",
Tags: []string{"nsfw", "test"},
Languages: []string{"en-US", "fr-CH"},
Locations: []Location{{
Country: util.PtrToString("CH"),
State: util.PtrToString("Ticino"),
City: util.PtrToString("Lugano"),
PostalCode: util.PtrToString("6900"),
Latitude: nil,
Longitude: nil,
}},
ThumbnailURL: util.PtrToString("https://scrn.storni.info/2019-01-18_16-37-39-098537783.png"),
AccountID: nil,
ClaimAddress: &address,
Preview: nil,
},
Fee: &Fee{
FeeCurrency: "LBC",
FeeAmount: decimal.NewFromFloat(1.0),
FeeAddress: &address,
},
Author: util.PtrToString("Niko"),
License: util.PtrToString("FREE"),
LicenseURL: nil,
ReleaseTime: nil,
Duration: nil,
Preview: nil,
AllowDuplicateName: nil,
ChannelName: nil,
ChannelID: util.PtrToString("2e28aa6dbd41f959893907841f4e40d0ecb0ede9"),
ChannelAccountID: nil,
})
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_ChannelCreate(t *testing.T) {
d := NewClient("")
got, err := d.ChannelCreate("@Test"+fmt.Sprintf("%d", time.Now().Unix()), 13.37, ChannelCreateOptions{
ClaimCreateOptions: ClaimCreateOptions{
Title: "Mess with the channels",
Description: "And you'll get what you deserve",
Tags: []string{"we", "got", "tags"},
Languages: []string{"en-US"},
Locations: []Location{{
Country: util.PtrToString("CH"),
State: util.PtrToString("Ticino"),
City: util.PtrToString("Lugano"),
}},
ThumbnailURL: util.PtrToString("https://scrn.storni.info/2019-04-12_15-43-25-001592625.png"),
},
Email: util.PtrToString("niko@lbry.com"),
WebsiteURL: util.PtrToString("https://lbry.com"),
CoverURL: util.PtrToString("https://scrn.storni.info/2019-04-12_15-43-25-001592625.png"),
})
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_ChannelUpdate(t *testing.T) {
d := NewClient("")
got, err := d.ChannelUpdate("709868122fe3560a3929d6d63bdbc792d8306a6c", ChannelUpdateOptions{
ClearLanguages: util.PtrToBool(true),
ClearLocations: util.PtrToBool(true),
ClearTags: util.PtrToBool(true),
ChannelCreateOptions: ChannelCreateOptions{
ClaimCreateOptions: ClaimCreateOptions{
Title: "Mess with the channels",
Description: "And you'll get what you deserve",
Tags: []string{"we", "got", "more", "tags"},
Languages: []string{"en-US"},
Locations: []Location{{
Country: util.PtrToString("CH"),
State: util.PtrToString("Ticino"),
City: util.PtrToString("Lugano"),
}},
ThumbnailURL: util.PtrToString("https://scrn.storni.info/2019-04-12_15-43-25-001592625.png"),
},
Email: util.PtrToString("niko@lbry.com"),
WebsiteURL: util.PtrToString("https://lbry.com"),
CoverURL: util.PtrToString("https://scrn.storni.info/2019-04-12_15-43-25-001592625.png"),
}})
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_ChannelAbandon(t *testing.T) {
d := NewClient("")
channelName := "@TestToDelete" + fmt.Sprintf("%d", time.Now().Unix())
channelResponse, err := d.ChannelCreate(channelName, 13.37, ChannelCreateOptions{
ClaimCreateOptions: ClaimCreateOptions{
Title: "Mess with the channels",
Description: "And you'll get what you deserve",
Tags: []string{"we", "got", "tags"},
Languages: []string{"en-US"},
Locations: []Location{{
Country: util.PtrToString("CH"),
State: util.PtrToString("Ticino"),
City: util.PtrToString("Lugano"),
}},
ThumbnailURL: util.PtrToString("https://scrn.storni.info/2019-04-12_15-43-25-001592625.png"),
},
Email: util.PtrToString("niko@lbry.com"),
WebsiteURL: util.PtrToString("https://lbry.com"),
CoverURL: util.PtrToString("https://scrn.storni.info/2019-04-12_15-43-25-001592625.png"),
})
if err != nil {
t.Error(err)
}
txID := channelResponse.Outputs[0].Txid
nout := channelResponse.Outputs[0].Nout
time.Sleep(10 * time.Second)
got, err := d.ChannelAbandon(txID, nout, nil, false)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_AddressList(t *testing.T) {
d := NewClient("")
got, err := d.AddressList(nil)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_ClaimList(t *testing.T) {
d := NewClient("")
got, err := d.ClaimList(nil, 1, 10)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_ClaimSearch(t *testing.T) {
d := NewClient("")
got, err := d.ClaimSearch(nil, util.PtrToString("1b2b530dfcef9885354f8f41190c8f678da5414e"), nil, nil)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_Status(t *testing.T) {
d := NewClient("")
got, err := d.Status()
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_UTXOList(t *testing.T) {
d := NewClient("")
got, err := d.UTXOList(nil)
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_Version(t *testing.T) {
d := NewClient("")
got, err := d.Version()
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_GetFile(t *testing.T) {
d := NewClient("")
got, err := d.Get("lbry://test1555965264")
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_FileList(t *testing.T) {
d := NewClient("")
got, err := d.FileList()
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_Resolve(t *testing.T) {
d := NewClient("")
got, err := d.Resolve("test1555965264")
if err != nil {
t.Error(err)
}
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_AccountSet(t *testing.T) {
d := NewClient("")
accounts, err := d.AccountList()
if err != nil {
t.Error(err)
}
account := (accounts.LBCRegtest)[0].ID
got, err := d.AccountSet(account, AccountSettings{ChangeMaxUses: 10000})
if err != nil {
t.Error(err)
}
prettyPrint(*got)
}
func TestClient_AccountCreate(t *testing.T) {
d := NewClient("")
account, err := d.AccountCreate("test"+fmt.Sprintf("%d", time.Now().Unix())+"@lbry.com", false)
if err != nil {
t.Error(err)
}
prettyPrint(*account)
}

View file

@ -1,11 +1,18 @@
package jsonrpc
import (
"encoding/hex"
"encoding/json"
"io/ioutil"
"net/http"
"os"
"reflect"
"github.com/lbryio/lbry.go/extras/errors"
lbryschema "github.com/lbryio/types/v1/go"
"github.com/lbryio/lbry.go/stream"
schema "github.com/lbryio/lbryschema.go/claim"
lbryschema "github.com/lbryio/types/v2/go"
"github.com/shopspring/decimal"
)
@ -19,44 +26,9 @@ const (
)
type Fee struct {
Currency Currency `json:"currency"`
Amount decimal.Decimal `json:"amount"`
Address *string `json:"address"`
}
type Support struct {
Amount decimal.Decimal `json:"amount"`
Nout int `json:"nout"`
Txid string `json:"txid"`
}
type Claim struct {
Address string `json:"address"`
Amount decimal.Decimal `json:"amount"`
BlocksToExpiration int `json:"blocks_to_expiration"`
Category string `json:"category"`
ClaimID string `json:"claim_id"`
ClaimSequence int `json:"claim_sequence"`
Confirmations int `json:"confirmations"`
DecodedClaim bool `json:"decoded_claim"`
Depth int `json:"depth"`
EffectiveAmount decimal.Decimal `json:"effective_amount"`
ExpirationHeight int `json:"expiration_height"`
Expired bool `json:"expired"`
Height int `json:"height"`
Hex string `json:"hex"`
IsSpent bool `json:"is_spent"`
Name string `json:"name"`
Nout int `json:"nout"`
PermanentUrl string `json:"permanent_url"`
Supports []Support `json:"supports"`
Txid string `json:"txid"`
ValidAtHeight int `json:"valid_at_height"`
Value lbryschema.Claim `json:"value"`
Error *string `json:"error,omitempty"`
ChannelName *string `json:"channel_name,omitempty"`
HasSignature *bool `json:"has_signature,omitempty"`
SignatureIsValid *bool `json:"signature_is_valid,omitempty"`
FeeCurrency Currency `json:"fee_currency"`
FeeAmount decimal.Decimal `json:"fee_amount"`
FeeAddress *string `json:"fee_address"`
}
type File struct {
@ -67,7 +39,7 @@ type File struct {
FileName string `json:"file_name"`
Key string `json:"key"`
Message string `json:"message"`
Metadata *lbryschema.Claim `json:"metadata"`
Metadata *lbryschema.Claim `json:"protobuf"`
MimeType string `json:"mime_type"`
Name string `json:"name"`
Outpoint string `json:"outpoint"`
@ -128,126 +100,27 @@ func fixDecodeProto(src, dest reflect.Type, data interface{}) (interface{}, erro
return d, nil
}
case reflect.TypeOf(lbryschema.Metadata_Version(0)):
val, err := getEnumVal(lbryschema.Metadata_Version_value, data)
return lbryschema.Metadata_Version(val), err
case reflect.TypeOf(lbryschema.Metadata_Language(0)):
val, err := getEnumVal(lbryschema.Metadata_Language_value, data)
return lbryschema.Metadata_Language(val), err
case reflect.TypeOf(lbryschema.Stream_Version(0)):
val, err := getEnumVal(lbryschema.Stream_Version_value, data)
return lbryschema.Stream_Version(val), err
case reflect.TypeOf(lbryschema.Claim_Version(0)):
val, err := getEnumVal(lbryschema.Claim_Version_value, data)
return lbryschema.Claim_Version(val), err
case reflect.TypeOf(lbryschema.Claim_ClaimType(0)):
val, err := getEnumVal(lbryschema.Claim_ClaimType_value, data)
return lbryschema.Claim_ClaimType(val), err
case reflect.TypeOf(lbryschema.Fee_Version(0)):
val, err := getEnumVal(lbryschema.Fee_Version_value, data)
return lbryschema.Fee_Version(val), err
case reflect.TypeOf(lbryschema.Fee_Currency(0)):
val, err := getEnumVal(lbryschema.Fee_Currency_value, data)
return lbryschema.Fee_Currency(val), err
case reflect.TypeOf(lbryschema.Claim{}):
blockChainName := os.Getenv("BLOCKCHAIN_NAME")
if blockChainName == "" {
blockChainName = "lbrycrd_main"
}
case reflect.TypeOf(lbryschema.Source_Version(0)):
val, err := getEnumVal(lbryschema.Source_Version_value, data)
return lbryschema.Source_Version(val), err
case reflect.TypeOf(lbryschema.Source_SourceTypes(0)):
val, err := getEnumVal(lbryschema.Source_SourceTypes_value, data)
return lbryschema.Source_SourceTypes(val), err
case reflect.TypeOf(lbryschema.KeyType(0)):
val, err := getEnumVal(lbryschema.KeyType_value, data)
return lbryschema.KeyType(val), err
case reflect.TypeOf(lbryschema.Signature_Version(0)):
val, err := getEnumVal(lbryschema.Signature_Version_value, data)
return lbryschema.Signature_Version(val), err
case reflect.TypeOf(lbryschema.Certificate_Version(0)):
val, err := getEnumVal(lbryschema.Certificate_Version_value, data)
return lbryschema.Certificate_Version(val), err
claim, err := schema.DecodeClaimHex(data.(string), blockChainName)
if err != nil {
return nil, err
}
return claim.Claim, nil
}
return data, nil
}
type CommandsResponse []string
type WalletBalanceResponse decimal.Decimal
type VersionResponse struct {
Build string `json:"build"`
LbrynetVersion string `json:"lbrynet_version"`
LbryschemaVersion string `json:"lbryschema_version"`
LbryumVersion string `json:"lbryum_version"`
OsRelease string `json:"os_release"`
OsSystem string `json:"os_system"`
Platform string `json:"platform"`
Processor string `json:"processor"`
PythonVersion string `json:"python_version"`
}
type StatusResponse struct {
BlobManager struct {
FinishedBlobs int `json:"finished_blobs"`
} `json:"blob_manager"`
ConnectionStatus struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"connection_status"`
Dht struct {
NodeID string `json:"node_id"`
PeersInRoutingTable int `json:"peers_in_routing_table"`
} `json:"dht"`
FileManager struct {
ManagedFiles int `json:"managed_files"`
} `json:"file_manager"`
HashAnnouncer struct {
AnnounceQueueSize int `json:"announce_queue_size"`
} `json:"hash_announcer"`
InstallationID string `json:"installation_id"`
IsFirstRun bool `json:"is_first_run"`
IsRunning bool `json:"is_running"`
SkippedComponents []string `json:"skipped_components"`
StartupStatus struct {
BlobManager bool `json:"blob_manager"`
BlockchainHeaders bool `json:"blockchain_headers"`
Database bool `json:"database"`
Dht bool `json:"dht"`
ExchangeRateManager bool `json:"exchange_rate_manager"`
FileManager bool `json:"file_manager"`
HashAnnouncer bool `json:"hash_announcer"`
PaymentRateManager bool `json:"payment_rate_manager"`
PeerProtocolServer bool `json:"peer_protocol_server"`
RateLimiter bool `json:"rate_limiter"`
StreamIdentifier bool `json:"stream_identifier"`
Upnp bool `json:"upnp"`
Wallet bool `json:"wallet"`
} `json:"startup_status"`
Wallet struct {
BestBlockchain string `json:"best_blockchain"`
Blocks int `json:"blocks"`
BlocksBehind int `json:"blocks_behind"`
IsEncrypted bool `json:"is_encrypted"`
} `json:"wallet"`
}
type ClaimListResponse struct {
Claims []Claim `json:"claims"`
LastTakeoverHeight int `json:"last_takeover_height"`
SupportsWithoutClaims []Support `json:"supports_without_claims"`
}
type ClaimListMineResponse []Claim
type ClaimShowResponse Claim
type ClaimAbandonResponse struct {
Txid string `json:"txid"`
Fee float64 `json:"fee"`
}
type PeerListResponsePeer struct {
IP string `json:"host"`
Port uint `json:"port"`
@ -295,57 +168,8 @@ type StreamAvailabilityResponse struct {
type GetResponse File
type FileListResponse []File
type ResolveResponse map[string]ResolveResponseItem
type ResolveResponseItem struct {
Certificate *Claim `json:"certificate,omitempty"`
Claim *Claim `json:"claim,omitempty"`
ClaimsInChannel *uint64 `json:"claims_in_channel,omitempty"`
Error *string `json:"error,omitempty"`
}
type ChannelNewResponse struct {
ClaimID string `json:"claim_id"`
Fee decimal.Decimal `json:"fee"`
Nout int `json:"nout"`
Success bool `json:"success"`
Tx string `json:"tx"`
Txid string `json:"txid"`
}
type ChannelListSingleResponse struct {
Address string `json:"address"`
Amount decimal.Decimal `json:"amount"`
BlocksToExpiration int `json:"blocks_to_expiration"`
CanSign bool `json:"can_sign"`
Category string `json:"category"`
ClaimID string `json:"claim_id"`
Confirmations int `json:"confirmations"`
DecodedClaim bool `json:"decoded_claim"`
ExpirationHeight int `json:"expiration_height"`
Expired bool `json:"expired"`
HasSignature bool `json:"has_signature"`
Height int `json:"height"`
Hex string `json:"hex"`
IsPending bool `json:"is_pending"`
IsSpent bool `json:"is_spent"`
Name string `json:"name"`
Nout int `json:"nout"`
Txid string `json:"txid"`
Value *lbryschema.Claim `json:"value"`
}
type ChannelListResponse []ChannelListSingleResponse
type WalletListResponse []string
type PublishResponse struct {
ClaimID string `json:"claim_id"`
Fee decimal.Decimal `json:"fee"`
Nout int `json:"nout"`
Tx string `json:"tx"`
Txid string `json:"txid"`
}
type BlobAnnounceResponse bool
type WalletPrefillAddressesResponse struct {
@ -354,9 +178,251 @@ type WalletPrefillAddressesResponse struct {
Hex string `json:"hex"`
}
type WalletNewAddressResponse string
type WalletUnusedAddressResponse string
type Account struct {
AddressGenerator struct {
Change struct {
Gap uint64 `json:"gap"`
MaximumUsesPerAddress uint64 `json:"maximum_uses_per_address"`
} `json:"change"`
Name string `json:"name"`
Receiving struct {
Gap uint64 `json:"gap"`
MaximumUsesPerAddress uint64 `json:"maximum_uses_per_address"`
} `json:"receiving"`
} `json:"address_generator"`
Certificates uint64 `json:"certificates"`
Coins float64 `json:"coins"`
Encrypted bool `json:"encrypted"`
ID string `json:"id"`
IsDefault bool `json:"is_default"`
Name string `json:"name"`
PublicKey string `json:"public_key"`
Satoshis uint64 `json:"satoshis"`
}
type AccountListResponse struct {
LBCMainnet []Account `json:"lbc_mainnet"`
LBCTestnet []Account `json:"lbc_testnet"`
LBCRegtest []Account `json:"lbc_regtest"`
}
type AccountBalanceResponse string
type AccountCreateResponse struct {
Account
PrivateKey string `json:"private_key,omitempty"`
PublicKey string `json:"public_key"`
Seed string `json:"seed"`
Ledger string `json:"ledger"`
ModifiedOn float64 `json:"modified_on"`
}
type Transaction struct {
Address string `json:"address"`
Amount string `json:"amount"`
ClaimID string `json:"claim_id"`
Confirmations int `json:"confirmations"`
Height int `json:"height"`
IsChange bool `json:"is_change"`
IsMine bool `json:"is_mine"`
Name string `json:"name"`
Nout uint64 `json:"nout"`
PermanentUrl string `json:"permanent_url"`
Protobuf string `json:"protobuf,omitempty"`
Txid string `json:"txid"`
Type string `json:"type"`
Value *lbryschema.Claim `json:"protobuf"`
}
type TransactionSummary struct {
Height int `json:"height"`
Hex string `json:"hex"`
Inputs []Transaction `json:"inputs"`
Outputs []Transaction `json:"outputs"`
TotalFee string `json:"total_fee"`
TotalOutput string `json:"total_output"`
Txid string `json:"txid"`
}
type AccountFundResponse TransactionSummary
type Address string
type AddressUnusedResponse Address
type AddressListResponse []Address
type ChannelListResponse struct {
Items []Transaction `json:"items"`
Page uint64 `json:"page"`
PageSize uint64 `json:"page_size"`
TotalPages uint64 `json:"total_pages"`
}
type ClaimAbandonResponse struct {
Success bool `json:"success"`
Tx TransactionSummary `json:"tx"`
}
type Support struct {
Amount string `json:"amount"`
Nout uint64 `json:"nout"`
Txid string `json:"txid"`
}
type Claim struct {
Address string `json:"address"`
Amount string `json:"amount"`
ClaimID string `json:"claim_id"`
ClaimOp string `json:"claim_op,omitempty"`
Confirmations int `json:"confirmations"`
Height int `json:"height"`
IsChange bool `json:"is_change,omitempty"`
IsChannelSignatureValid bool `json:"is_channel_signature_valid,omitempty"`
IsMine bool `json:"is_mine,omitempty"`
Name string `json:"name"`
Nout uint64 `json:"nout"`
PermanentURL string `json:"permanent_url"`
SigningChannel struct {
ClaimID string `json:"claim_id"`
Name string `json:"name"`
Value struct {
PublicKey string `json:"public_key"`
Title string `json:"title"`
} `json:"value"`
} `json:"signing_channel,omitempty"`
Timestamp int `json:"timestamp"`
Txid string `json:"txid"`
Type string `json:"type,omitempty"`
ValueType string `json:"value_type,omitempty"`
Value lbryschema.Claim `json:"protobuf,omitempty"`
AbsoluteChannelPosition int `json:"absolute_channel_position,omitempty"`
ChannelName string `json:"channel_name,omitempty"`
ClaimSequence int64 `json:"claim_sequence,omitempty"`
DecodedClaim bool `json:"decoded_claim,omitempty"`
EffectiveAmount string `json:"effective_amount,omitempty"`
HasSignature *bool `json:"has_signature,omitempty"`
SignatureIsValid *bool `json:"signature_is_valid,omitempty"`
Supports []Support `json:"supports,omitempty"`
ValidAtHeight int `json:"valid_at_height,omitempty"`
}
const reflectorURL = "http://blobs.lbry.io/"
// 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() (uint64, 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
var streamSize uint64 = 0
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)
}
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
}
type ClaimListResponse struct {
Claims []Claim `json:"items"`
Page uint64 `json:"page"`
PageSize uint64 `json:"page_size"`
TotalPages uint64 `json:"total_pages"`
}
type ClaimSearchResponse ClaimListResponse
type StatusResponse struct {
BlobManager struct {
FinishedBlobs uint64 `json:"finished_blobs"`
} `json:"blob_manager"`
ConnectionStatus struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"connection_status"`
Dht struct {
NodeID string `json:"node_id"`
PeersInRoutingTable uint64 `json:"peers_in_routing_table"`
} `json:"dht"`
HashAnnouncer struct {
AnnounceQueueSize uint64 `json:"announce_queue_size"`
} `json:"hash_announcer"`
InstallationID string `json:"installation_id"`
IsFirstRun bool `json:"is_first_run"`
IsRunning bool `json:"is_running"`
SkippedComponents []string `json:"skipped_components"`
StartupStatus struct {
BlobManager bool `json:"blob_manager"`
BlockchainHeaders bool `json:"blockchain_headers"`
Database bool `json:"database"`
Dht bool `json:"dht"`
ExchangeRateManager bool `json:"exchange_rate_manager"`
HashAnnouncer bool `json:"hash_announcer"`
PeerProtocolServer bool `json:"peer_protocol_server"`
StreamManager bool `json:"stream_manager"`
Upnp bool `json:"upnp"`
Wallet bool `json:"wallet"`
} `json:"startup_status"`
StreamManager struct {
ManagedFiles int64 `json:"managed_files"`
} `json:"stream_manager"`
Upnp struct {
AioupnpVersion string `json:"aioupnp_version"`
DhtRedirectSet bool `json:"dht_redirect_set"`
ExternalIp string `json:"external_ip"`
Gateway string `json:"gateway"`
PeerRedirectSet bool `json:"peer_redirect_set"`
Redirects struct{} `json:"redirects"`
}
Wallet struct {
BestBlochash string `json:"best_blockhash"`
Blocks int `json:"blocks"`
BlocksBehind int `json:"blocks_behind"`
IsEncrypted bool `json:"is_encrypted"`
IsLocked bool `json:"is_locked"`
} `json:"wallet"`
}
type UTXOListResponse []struct {
Address string `json:"address"`
Amount decimal.Decimal `json:"amount"`
Amount string `json:"amount"`
Height int `json:"height"`
IsClaim bool `json:"is_claim"`
IsCoinbase bool `json:"is_coinbase"`
@ -366,11 +432,40 @@ type UTXOListResponse []struct {
Txid string `json:"txid"`
}
type WalletNewAddressResponse string
type VersionResponse struct {
Build string `json:"build"`
Desktop string `json:"desktop"`
Distro struct {
Codename string `json:"codename"`
ID string `json:"id"`
Like string `json:"like"`
Version string `json:"version"`
VersionParts struct {
BuildNumber string `json:"build_number"`
Major string `json:"major"`
Minor string `json:"minor"`
} `json:"version_parts"`
} `json:"distro"`
LbrynetVersion string `json:"lbrynet_version"`
LbryschemaVersion string `json:"lbryschema_version"`
OsRelease string `json:"os_release"`
OsSystem string `json:"os_system"`
Platform string `json:"platform"`
Processor string `json:"processor"`
PythonVersion string `json:"python_version"`
}
type WalletUnusedAddressResponse string
type ResolveResponse map[string]ResolveResponseItem
type ResolveResponseItem struct {
Certificate *Claim `json:"certificate,omitempty"`
Claim *Claim `json:"claim,omitempty"`
ClaimsInChannel *uint64 `json:"claims_in_channel,omitempty"`
Error *string `json:"error,omitempty"`
}
type NumClaimsInChannelResponse map[string]struct {
ClaimsInChannel uint64 `json:"claims_in_channel,omitempty"`
Error string `json:"error,omitempty"`
ClaimsInChannel *uint64 `json:"claims_in_channel,omitempty"`
Error *string `json:"error,omitempty"`
}
type ClaimShowResponse *Claim

56
extras/util/pointer.go Normal file
View file

@ -0,0 +1,56 @@
// mostly copied from github.com/AlekSi/pointer
// Provides helpers to get pointers to values of build-in types.
package util
import (
"time"
"github.com/lbryio/lbry.go/extras/null"
)
func PtrToBool(b bool) *bool { return &b }
func PtrToByte(b byte) *byte { return &b }
func PtrToComplex128(c complex128) *complex128 { return &c }
func PtrToComplex64(c complex64) *complex64 { return &c }
func PtrToError(e error) *error { return &e }
func PtrToFloat32(f float32) *float32 { return &f }
func PtrToFloat64(f float64) *float64 { return &f }
func PtrToInt(i int) *int { return &i }
func PtrToInt16(i int16) *int16 { return &i }
func PtrToInt32(i int32) *int32 { return &i }
func PtrToInt64(i int64) *int64 { return &i }
func PtrToInt8(i int8) *int8 { return &i }
func PtrToRune(r rune) *rune { return &r }
func PtrToString(s string) *string { return &s }
func PtrToTime(t time.Time) *time.Time { return &t }
func PtrToUint(u uint) *uint { return &u }
func PtrToUint16(u uint16) *uint16 { return &u }
func PtrToUint32(u uint32) *uint32 { return &u }
func PtrToUint64(u uint64) *uint64 { return &u }
func PtrToUint8(u uint8) *uint8 { return &u }
func PtrToUintptr(u uintptr) *uintptr { return &u }
func PtrToNullString(s string) *null.String { n := null.StringFrom(s); return &n }
func PtrToNullUint64(u uint64) *null.Uint64 { n := null.Uint64From(u); return &n }
func StrFromPtr(ptr *string) string {
if ptr == nil {
return ""
}
return *ptr
}
func StrFromNull(str null.String) string {
if !str.Valid {
return ""
}
return str.String
}
func NullStringFrom(s string) null.String {
if s == "" {
return null.String{}
}
return null.StringFrom(s)
}

6
go.mod
View file

@ -8,10 +8,12 @@ require (
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
github.com/davecgh/go-spew v1.1.0
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
@ -19,8 +21,9 @@ require (
github.com/gorilla/websocket v1.2.0 // indirect
github.com/jtolds/gls v4.2.1+incompatible // indirect
github.com/lbryio/errors.go v0.0.0-20180223142025-ad03d3cc6a5c
github.com/lbryio/lbryschema.go v0.0.0-20190428231007-c54836bca002
github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04
github.com/lbryio/types v0.0.0-20190405005919-54c3c28f676a
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
@ -48,4 +51,5 @@ require (
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
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
)

16
go.sum
View file

@ -14,6 +14,8 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
@ -29,6 +31,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
@ -46,12 +50,12 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/lbryio/errors.go v0.0.0-20180223142025-ad03d3cc6a5c h1:BhdcWGsuKif/XoSZnqVGNqJ1iEmH0czWR5upj+AuR8M=
github.com/lbryio/errors.go v0.0.0-20180223142025-ad03d3cc6a5c/go.mod h1:muH7wpUqE8hRA3OrYYosw9+Sl681BF9cwcjzE+OCNK8=
github.com/lbryio/lbryschema.go v0.0.0-20190428231007-c54836bca002 h1:urfYK5ElpUrAv90auPLldoVC60LwiGAcY0OE6HJB9KI=
github.com/lbryio/lbryschema.go v0.0.0-20190428231007-c54836bca002/go.mod h1:dAzPCBj3CKKWBGYBZxK6tKBP5SCgY2tqd9SnQd/OyKo=
github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04 h1:Nze+C2HbeKvhjI/kVn+9Poj/UuEW5sOQxcsxqO7L3GI=
github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04/go.mod h1:fbG/dzobG8r95KzMwckXiLMHfFjZaBRQqC9hPs2XAQ4=
github.com/lbryio/types v0.0.0-20190304154608-a6f2fd6d5f38 h1:78rErXiBhMjs7vh4Ke3ZMqQjf+pnQeNrkXYmQ8L6aKE=
github.com/lbryio/types v0.0.0-20190304154608-a6f2fd6d5f38/go.mod h1:CG3wsDv5BiVYQd5i1Jp7wGsaVyjZTJshqXeWMVKsISE=
github.com/lbryio/types v0.0.0-20190405005919-54c3c28f676a h1:twWvrsBDvSb+qnmpSq3nvFrodgC5PpXUipyo4T/W790=
github.com/lbryio/types v0.0.0-20190405005919-54c3c28f676a/go.mod h1:CG3wsDv5BiVYQd5i1Jp7wGsaVyjZTJshqXeWMVKsISE=
github.com/lbryio/types v0.0.0-20190422033210-321fb2abda9c h1:m3O7561xBQ00lfUVayW4c6SnpVbUDQtPUwGcGYSUYQA=
github.com/lbryio/types v0.0.0-20190422033210-321fb2abda9c/go.mod h1:CG3wsDv5BiVYQd5i1Jp7wGsaVyjZTJshqXeWMVKsISE=
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 h1:AsEBgzv3DhuYHI/GiQh2HxvTP71HCCE9E/tzGUzGdtU=
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5/go.mod h1:c2mYKRyMb1BPkO5St0c/ps62L4S0W2NAkaTXj9qEI+0=
github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 h1:iOAVXzZyXtW408TMYejlUPo6BIn92HmOacWtIfNyYns=
@ -60,8 +64,6 @@ github.com/lyoshenka/bencode v0.0.0-20180323155644-b7abd7672df5 h1:mG83tLXWSRdcX
github.com/lyoshenka/bencode v0.0.0-20180323155644-b7abd7672df5/go.mod h1:H0aPCWffGOaDcjkw1iB7W9DVLp6GXmfcJY/7YZCWPA4=
github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 h1:/rdJjIiKG5rRdwG5yxHmSE/7ZREjpyC0kL7GxGT/qJw=
github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/nlopes/slack v0.2.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
github.com/nlopes/slack v0.3.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
github.com/nlopes/slack v0.5.0 h1:NbIae8Kd0NpqaEI3iUrsuS0KbcEDhzhc939jLW5fNm0=
github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
@ -137,4 +139,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

7
scripts/deploy.sh Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
export IMPORTPATH="github.com/lbryio/lbry.go"
export VERSIONSHORT="${TRAVIS_COMMIT:-"$(git describe --tags --always --dirty)"}"
export VERSIONLONG="${TRAVIS_COMMIT:-"$(git describe --tags --always --dirty --long)"}"
export COMMITMSG="$(echo ${TRAVIS_COMMIT_MESSAGE:-"$(git show -s --format=%s)"} | tr -d '"' | head -n 1)"
curl -sL https://git.io/goreleaser | bash

5
scripts/release.sh Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env bash
GO111MODULE=off go get github.com/caarlos0/svu
git tag `svu "$1"`
git push --tags