Generate typescript documentation from golang types

This commit is contained in:
Martin Boehm 2023-02-21 10:00:30 +01:00
parent 9ecfdfe11d
commit 15c19ac1fc
9 changed files with 682 additions and 160 deletions

11
.prettierrc Normal file
View File

@ -0,0 +1,11 @@
{
"printWidth": 100,
"arrowParens": "avoid",
"bracketSpacing": true,
"singleQuote": true,
"semi": true,
"trailingComma": "all",
"tabWidth": 4,
"useTabs": false,
"bracketSameLine": false
}

View File

@ -158,7 +158,7 @@ type MultiTokenValue struct {
// Token contains info about tokens held by an address // Token contains info about tokens held by an address
type Token struct { type Token struct {
Type bchain.TokenTypeName `json:"type"` Type bchain.TokenTypeName `json:"type" ts_type:"'XPUBAddress' | 'ERC20' | 'ERC721' | 'ERC1155'"`
Name string `json:"name"` Name string `json:"name"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
Contract string `json:"contract,omitempty"` Contract string `json:"contract,omitempty"`
@ -263,7 +263,7 @@ type Tx struct {
FeesSat *Amount `json:"fees,omitempty"` FeesSat *Amount `json:"fees,omitempty"`
Hex string `json:"hex,omitempty"` Hex string `json:"hex,omitempty"`
Rbf bool `json:"rbf,omitempty"` Rbf bool `json:"rbf,omitempty"`
CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty"` CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty" ts_type:"any"`
TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"` TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"`
EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"` EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"`
AddressAliases AddressAliasesMap `json:"addressAliases,omitempty"` AddressAliases AddressAliasesMap `json:"addressAliases,omitempty"`

412
blockbook-api.d.ts vendored Normal file
View File

@ -0,0 +1,412 @@
/* Do not change, this code is generated from Golang structs */
export interface APIError {
Text: string;
Public: boolean;
}
export interface AddressAlias {
Type: string;
Alias: string;
}
export interface EthereumInternalTransfer {
type: number;
from: string;
to: string;
value?: string;
}
export interface EthereumParsedInputParam {
type: string;
values?: string[];
}
export interface EthereumParsedInputData {
methodId: string;
name: string;
function?: string;
params?: EthereumParsedInputParam[];
}
export interface EthereumSpecific {
type?: number;
createdContract?: string;
status: number;
error?: string;
nonce: number;
gasLimit?: string;
gasUsed?: string;
gasPrice?: string;
data?: string;
parsedData?: EthereumParsedInputData;
internalTransfers?: EthereumInternalTransfer[];
}
export interface MultiTokenValue {
id?: string;
value?: string;
}
export interface TokenTransfer {
type: string;
from: string;
to: string;
contract: string;
name: string;
symbol: string;
decimals: number;
value?: string;
multiTokenValues?: MultiTokenValue[];
}
export interface Vout {
value?: string;
n: number;
spent?: boolean;
spentTxId?: string;
spentIndex?: number;
spentHeight?: number;
hex?: string;
asm?: string;
addresses: string[];
isAddress: boolean;
isOwn?: boolean;
type?: string;
}
export interface Vin {
txid?: string;
vout?: number;
sequence?: number;
n: number;
addresses?: string[];
isAddress: boolean;
isOwn?: boolean;
value?: string;
hex?: string;
asm?: string;
coinbase?: string;
}
export interface Tx {
txid: string;
version?: number;
lockTime?: number;
vin: Vin[];
vout: Vout[];
blockHash?: string;
blockHeight: number;
confirmations: number;
confirmationETABlocks?: number;
confirmationETASeconds?: number;
blockTime: number;
size?: number;
vsize?: number;
value?: string;
valueIn?: string;
fees?: string;
hex?: string;
rbf?: boolean;
coinSpecificData?: any;
tokenTransfers?: TokenTransfer[];
ethereumSpecific?: EthereumSpecific;
addressAliases?: { [key: string]: AddressAlias };
}
export interface FeeStats {
txCount: number;
totalFeesSat?: string;
averageFeePerKb: number;
decilesFeePerKb: number[];
}
export interface ContractInfo {
type: string;
contract: string;
name: string;
symbol: string;
decimals: number;
createdInBlock?: number;
destructedInBlock?: number;
}
export interface Token {
type: 'XPUBAddress' | 'ERC20' | 'ERC721' | 'ERC1155';
name: string;
path?: string;
contract?: string;
transfers: number;
symbol?: string;
decimals?: number;
balance?: string;
baseValue?: number;
secondaryValue?: number;
ids?: string[];
multiTokenValues?: MultiTokenValue[];
totalReceived?: string;
totalSent?: string;
}
export interface Address {
page?: number;
totalPages?: number;
itemsOnPage?: number;
address: string;
balance?: string;
totalReceived?: string;
totalSent?: string;
unconfirmedBalance?: string;
unconfirmedTxs: number;
txs: number;
nonTokenTxs?: number;
internalTxs?: number;
transactions?: Tx[];
txids?: string[];
nonce?: string;
usedTokens?: number;
tokens?: Token[];
secondaryValue?: number;
tokensBaseValue?: number;
tokensSecondaryValue?: number;
totalBaseValue?: number;
totalSecondaryValue?: number;
contractInfo?: ContractInfo;
erc20Contract?: ContractInfo;
addressAliases?: { [key: string]: AddressAlias };
}
export interface Utxo {
txid: string;
vout: number;
value?: string;
height?: number;
confirmations: number;
address?: string;
path?: string;
lockTime?: number;
coinbase?: boolean;
}
export interface BalanceHistory {
time: number;
txs: number;
received?: string;
sent?: string;
sentToSelf?: string;
rates?: { [key: string]: number };
txid?: string;
}
export interface BlockInfo {
Hash: string;
Time: number;
Txs: number;
Size: number;
Height: number;
}
export interface Blocks {
page?: number;
totalPages?: number;
itemsOnPage?: number;
blocks: BlockInfo[];
}
export interface Block {
page?: number;
totalPages?: number;
itemsOnPage?: number;
hash: string;
previousBlockHash?: string;
nextBlockHash?: string;
height: number;
confirmations: number;
size: number;
time?: number;
version: string;
merkleRoot: string;
nonce: string;
bits: string;
difficulty: string;
tx?: string[];
txCount: number;
txs?: Tx[];
addressAliases?: { [key: string]: AddressAlias };
}
export interface BlockRaw {
hex: string;
}
export interface BackendInfo {
error?: string;
chain?: string;
blocks?: number;
headers?: number;
bestBlockHash?: string;
difficulty?: string;
sizeOnDisk?: number;
version?: string;
subversion?: string;
protocolVersion?: string;
timeOffset?: number;
warnings?: string;
consensus_version?: string;
consensus?: any;
}
export interface InternalStateColumn {
name: string;
version: number;
rows: number;
keyBytes: number;
valueBytes: number;
updated: string;
}
export interface BlockbookInfo {
coin: string;
host: string;
version: string;
gitCommit: string;
buildTime: string;
syncMode: boolean;
initialSync: boolean;
inSync: boolean;
bestHeight: number;
lastBlockTime: string;
inSyncMempool: boolean;
lastMempoolTime: string;
mempoolSize: number;
decimals: number;
dbSize: number;
hasFiatRates?: boolean;
hasTokenFiatRates?: boolean;
currentFiatRatesTime?: string;
historicalFiatRatesTime?: string;
historicalTokenFiatRatesTime?: string;
dbSizeFromColumns?: number;
dbColumns?: InternalStateColumn[];
about: string;
}
export interface SystemInfo {
blockbook?: BlockbookInfo;
backend?: BackendInfo;
}
export interface FiatTicker {
ts?: number;
rates: { [key: string]: number };
error?: string;
}
export interface FiatTickers {
tickers: FiatTicker[];
}
export interface AvailableVsCurrencies {
ts?: number;
available_currencies: string[];
error?: string;
}
export interface WsReq {
id: string;
method:
| 'getAccountInfo'
| 'getInfo'
| 'getBlockHash'
| 'getAccountUtxo'
| 'getBalanceHistory'
| 'getTransaction'
| 'getTransactionSpecific'
| 'estimateFee'
| 'sendTransaction'
| 'subscribeNewBlock'
| 'unsubscribeNewBlock'
| 'subscribeNewTransaction'
| 'unsubscribeNewTransaction'
| 'subscribeAddresses'
| 'unsubscribeAddresses'
| 'subscribeFiatRates'
| 'unsubscribeFiatRates'
| 'ping'
| 'getCurrentFiatRates'
| 'getFiatRatesForTimestamps'
| 'getFiatRatesTickersList';
params: any;
}
export interface WsRes {
id: string;
data: any;
}
export interface WsAccountInfoReq {
descriptor: string;
details?: 'basic' | 'tokens' | 'tokenBalances' | 'txids' | 'txslight' | 'txs';
tokens?: 'derived' | 'used' | 'nonzero';
pageSize?: number;
page?: number;
from?: number;
to?: number;
contractFilter?: string;
secondaryCurrency?: string;
gap?: number;
}
export interface WsBackendInfo {
version?: string;
subversion?: string;
consensus_version?: string;
consensus?: any;
}
export interface WsInfoRes {
name: string;
shortcut: string;
decimals: number;
version: string;
bestHeight: number;
bestHash: string;
block0Hash: string;
testnet: boolean;
backend: WsBackendInfo;
}
export interface WsBlockHashReq {
height: number;
}
export interface WsBlockHashRes {
hash: string;
}
export interface WsBlockReq {
id: string;
pageSize?: number;
page?: number;
}
export interface WsAccountUtxoReq {
descriptor: string;
}
export interface WsBalanceHistoryReq {
descriptor: string;
from?: number;
to?: number;
currencies?: string[];
gap?: number;
groupBy?: number;
}
export interface WsTransactionReq {
txid: string;
}
export interface WsTransactionSpecificReq {
txid: string;
}
export interface WsEstimateFeeReq {
blocks?: number[];
specific?: {
conservative?: boolean;
txsize?: number;
from?: string;
to?: string;
data?: string;
value?: string;
};
}
export interface WsEstimateFeeRes {
feePerTx?: string;
feePerUnit?: string;
feeLimit?: string;
}
export interface WsSendTransactionReq {
hex: string;
}
export interface WsSubscribeAddressesReq {
addresses: string[];
}
export interface WsSubscribeFiatRatesReq {
currency?: string;
tokens?: string[];
}
export interface WsCurrentFiatRatesReq {
currencies?: string[];
token?: string;
}
export interface WsFiatRatesForTimestampsReq {
timestamps: number[];
currencies?: string[];
token?: string;
}
export interface WsFiatRatesTickersListReq {
timestamp?: number;
token?: string;
}

View File

@ -0,0 +1,65 @@
package main
import (
"fmt"
"math/big"
"time"
"github.com/tkrajina/typescriptify-golang-structs/typescriptify"
"github.com/trezor/blockbook/api"
"github.com/trezor/blockbook/server"
)
func main() {
t := typescriptify.New()
t.CreateInterface = true
t.Indent = " "
t.BackupDir = ""
t.ManageType(api.Amount{}, typescriptify.TypeOptions{TSType: "string"})
t.ManageType([]api.Amount{}, typescriptify.TypeOptions{TSType: "string[]"})
t.ManageType(big.Int{}, typescriptify.TypeOptions{TSType: "string"})
t.ManageType(time.Time{}, typescriptify.TypeOptions{TSType: "string", TSDoc: "Time in ISO 8601 YYYY-MM-DDTHH:mm:ss.sssZd"})
// API - REST and Websocket
t.Add(api.APIError{})
t.Add(api.Tx{})
t.Add(api.FeeStats{})
t.Add(api.Address{})
t.Add(api.Utxo{})
t.Add(api.BalanceHistory{})
t.Add(api.Blocks{})
t.Add(api.Block{})
t.Add(api.BlockRaw{})
t.Add(api.SystemInfo{})
t.Add(api.FiatTicker{})
t.Add(api.FiatTickers{})
t.Add(api.AvailableVsCurrencies{})
// Websocket specific
t.Add(server.WsReq{})
t.Add(server.WsRes{})
t.Add(server.WsAccountInfoReq{})
t.Add(server.WsInfoRes{})
t.Add(server.WsBlockHashReq{})
t.Add(server.WsBlockHashRes{})
t.Add(server.WsBlockReq{})
t.Add(server.WsAccountUtxoReq{})
t.Add(server.WsBalanceHistoryReq{})
t.Add(server.WsTransactionReq{})
t.Add(server.WsTransactionSpecificReq{})
t.Add(server.WsEstimateFeeReq{})
t.Add(server.WsEstimateFeeRes{})
t.Add(server.WsSendTransactionReq{})
t.Add(server.WsSubscribeAddressesReq{})
t.Add(server.WsSubscribeFiatRatesReq{})
t.Add(server.WsCurrentFiatRatesReq{})
t.Add(server.WsFiatRatesForTimestampsReq{})
t.Add(server.WsFiatRatesTickersListReq{})
err := t.ConvertToFile("blockbook-api.d.ts")
if err != nil {
panic(err.Error())
}
fmt.Println("OK")
}

2
go.mod
View File

@ -75,6 +75,8 @@ require (
github.com/stretchr/testify v1.8.1 // indirect github.com/stretchr/testify v1.8.1 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect github.com/tklauser/numcpus v0.2.2 // indirect
github.com/tkrajina/go-reflector v0.5.5 // indirect
github.com/tkrajina/typescriptify-golang-structs v0.1.10 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 // indirect golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 // indirect
golang.org/x/sys v0.5.0 // indirect golang.org/x/sys v0.5.0 // indirect

4
go.sum
View File

@ -367,6 +367,10 @@ github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp
github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
github.com/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/tkrajina/typescriptify-golang-structs v0.1.10 h1:W/Ta9Kqo2lV+7bVXuQoUhZ0bDlnjwtPpKsy3A9M1nYg=
github.com/tkrajina/typescriptify-golang-structs v0.1.10/go.mod h1:sjU00nti/PMEOZb07KljFlR+lJ+RotsC0GBQMv9EKls=
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8= github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=

View File

@ -1262,7 +1262,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) {
"timestamps": []string{"yesterday"}, "timestamps": []string{"yesterday"},
}, },
}, },
want: `{"id":"23","data":{"error":{"message":"json: cannot unmarshal string into Go struct field .timestamps of type int64"}}}`, want: `{"id":"23","data":{"error":{"message":"json: cannot unmarshal string into Go struct field WsFiatRatesForTimestampsReq.timestamps of type int64"}}}`,
}, },
{ {
name: "websocket getFiatRatesForTimestamps empty currency", name: "websocket getFiatRatesForTimestamps empty currency",

View File

@ -34,21 +34,10 @@ var (
connectionCounter uint64 connectionCounter uint64
) )
type websocketReq struct {
ID string `json:"id"`
Method string `json:"method"`
Params json.RawMessage `json:"params"`
}
type websocketRes struct {
ID string `json:"id"`
Data interface{} `json:"data"`
}
type websocketChannel struct { type websocketChannel struct {
id uint64 id uint64
conn *websocket.Conn conn *websocket.Conn
out chan *websocketRes out chan *WsRes
ip string ip string
requestHeader http.Header requestHeader http.Header
alive bool alive bool
@ -56,11 +45,6 @@ type websocketChannel struct {
addrDescs []string // subscribed address descriptors as strings addrDescs []string // subscribed address descriptors as strings
} }
type fiatRatesSubscription struct {
Currency string `json:"currency"`
Tokens []string `json:"tokens"`
}
// WebsocketServer is a handle to websocket server // WebsocketServer is a handle to websocket server
type WebsocketServer struct { type WebsocketServer struct {
upgrader *websocket.Upgrader upgrader *websocket.Upgrader
@ -147,7 +131,7 @@ func (s *WebsocketServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c := &websocketChannel{ c := &websocketChannel{
id: atomic.AddUint64(&connectionCounter, 1), id: atomic.AddUint64(&connectionCounter, 1),
conn: conn, conn: conn,
out: make(chan *websocketRes, outChannelSize), out: make(chan *WsRes, outChannelSize),
ip: getIP(r), ip: getIP(r),
requestHeader: r.Header, requestHeader: r.Header,
alive: true, alive: true,
@ -184,7 +168,7 @@ func (c *websocketChannel) CloseOut() bool {
return false return false
} }
func (c *websocketChannel) DataOut(data *websocketRes) { func (c *websocketChannel) DataOut(data *WsRes) {
c.aliveLock.Lock() c.aliveLock.Lock()
defer c.aliveLock.Unlock() defer c.aliveLock.Unlock()
if c.alive { if c.alive {
@ -215,7 +199,7 @@ func (s *WebsocketServer) inputLoop(c *websocketChannel) {
} }
switch t { switch t {
case websocket.TextMessage: case websocket.TextMessage:
var req websocketReq var req WsReq
err := json.Unmarshal(d, &req) err := json.Unmarshal(d, &req)
if err != nil { if err != nil {
glog.Error("Error parsing message from ", c.id, ", ", string(d), ", ", err) glog.Error("Error parsing message from ", c.id, ", ", string(d), ", ", err)
@ -229,7 +213,6 @@ func (s *WebsocketServer) inputLoop(c *websocketChannel) {
return return
case websocket.PingMessage: case websocket.PingMessage:
c.conn.WriteControl(websocket.PongMessage, nil, time.Now().Add(defaultTimeout)) c.conn.WriteControl(websocket.PongMessage, nil, time.Now().Add(defaultTimeout))
break
case websocket.CloseMessage: case websocket.CloseMessage:
s.closeChannel(c) s.closeChannel(c)
return return
@ -270,36 +253,30 @@ func (s *WebsocketServer) onDisconnect(c *websocketChannel) {
s.metrics.WebsocketClients.Dec() s.metrics.WebsocketClients.Dec()
} }
var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *websocketReq) (interface{}, error){ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *WsReq) (interface{}, error){
"getAccountInfo": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getAccountInfo": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r, err := unmarshalGetAccountInfoRequest(req.Params) r, err := unmarshalGetAccountInfoRequest(req.Params)
if err == nil { if err == nil {
rv, err = s.getAccountInfo(r) rv, err = s.getAccountInfo(r)
} }
return return
}, },
"getInfo": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getInfo": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.getInfo() return s.getInfo()
}, },
"getBlockHash": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getBlockHash": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsBlockHashReq{}
Height int `json:"height"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.getBlockHash(r.Height) rv, err = s.getBlockHash(r.Height)
} }
return return
}, },
"getBlock": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getBlock": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
if !s.is.ExtendedIndex { if !s.is.ExtendedIndex {
return nil, errors.New("Not supported") return nil, errors.New("Not supported")
} }
r := struct { r := WsBlockReq{}
Id string `json:"id"`
PageSize int `json:"pageSize"`
Page int `json:"page"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if r.PageSize == 0 { if r.PageSize == 0 {
r.PageSize = 1000000 r.PageSize = 1000000
@ -309,25 +286,16 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *webs
} }
return return
}, },
"getAccountUtxo": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getAccountUtxo": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsAccountUtxoReq{}
Descriptor string `json:"descriptor"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.getAccountUtxo(r.Descriptor) rv, err = s.getAccountUtxo(r.Descriptor)
} }
return return
}, },
"getBalanceHistory": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getBalanceHistory": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsBalanceHistoryReq{}
Descriptor string `json:"descriptor"`
From int64 `json:"from"`
To int64 `json:"to"`
Currencies []string `json:"currencies"`
Gap int `json:"gap"`
GroupBy uint32 `json:"groupBy"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
if r.From <= 0 { if r.From <= 0 {
@ -346,63 +314,57 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *webs
} }
return return
}, },
"getTransaction": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getTransaction": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsTransactionReq{}
Txid string `json:"txid"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.getTransaction(r.Txid) rv, err = s.getTransaction(r.Txid)
} }
return return
}, },
"getTransactionSpecific": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getTransactionSpecific": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsTransactionSpecificReq{}
Txid string `json:"txid"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.getTransactionSpecific(r.Txid) rv, err = s.getTransactionSpecific(r.Txid)
} }
return return
}, },
"estimateFee": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "estimateFee": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.estimateFee(c, req.Params) return s.estimateFee(c, req.Params)
}, },
"sendTransaction": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "sendTransaction": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsSendTransactionReq{}
Hex string `json:"hex"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.sendTransaction(r.Hex) rv, err = s.sendTransaction(r.Hex)
} }
return return
}, },
"subscribeNewBlock": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "subscribeNewBlock": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.subscribeNewBlock(c, req) return s.subscribeNewBlock(c, req)
}, },
"unsubscribeNewBlock": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "unsubscribeNewBlock": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.unsubscribeNewBlock(c) return s.unsubscribeNewBlock(c)
}, },
"subscribeNewTransaction": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "subscribeNewTransaction": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.subscribeNewTransaction(c, req) return s.subscribeNewTransaction(c, req)
}, },
"unsubscribeNewTransaction": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "unsubscribeNewTransaction": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.unsubscribeNewTransaction(c) return s.unsubscribeNewTransaction(c)
}, },
"subscribeAddresses": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "subscribeAddresses": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
ad, err := s.unmarshalAddresses(req.Params) ad, err := s.unmarshalAddresses(req.Params)
if err == nil { if err == nil {
rv, err = s.subscribeAddresses(c, ad, req) rv, err = s.subscribeAddresses(c, ad, req)
} }
return return
}, },
"unsubscribeAddresses": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "unsubscribeAddresses": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.unsubscribeAddresses(c) return s.unsubscribeAddresses(c)
}, },
"subscribeFiatRates": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "subscribeFiatRates": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
var r fiatRatesSubscription var r WsSubscribeFiatRatesReq
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err != nil { if err != nil {
return nil, err return nil, err
@ -413,41 +375,31 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *webs
} }
return s.subscribeFiatRates(c, &r, req) return s.subscribeFiatRates(c, &r, req)
}, },
"unsubscribeFiatRates": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "unsubscribeFiatRates": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
return s.unsubscribeFiatRates(c) return s.unsubscribeFiatRates(c)
}, },
"ping": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "ping": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct{}{} r := struct{}{}
return r, nil return r, nil
}, },
"getCurrentFiatRates": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getCurrentFiatRates": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsCurrentFiatRatesReq{}
Currencies []string `json:"currencies"`
Token string `json:"token"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.getCurrentFiatRates(r.Currencies, r.Token) rv, err = s.getCurrentFiatRates(r.Currencies, r.Token)
} }
return return
}, },
"getFiatRatesForTimestamps": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getFiatRatesForTimestamps": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsFiatRatesForTimestampsReq{}
Timestamps []int64 `json:"timestamps"`
Currencies []string `json:"currencies"`
Token string `json:"token"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.getFiatRatesForTimestamps(r.Timestamps, r.Currencies, r.Token) rv, err = s.getFiatRatesForTimestamps(r.Timestamps, r.Currencies, r.Token)
} }
return return
}, },
"getFiatRatesTickersList": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { "getFiatRatesTickersList": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) {
r := struct { r := WsFiatRatesTickersListReq{}
Timestamp int64 `json:"timestamp"`
Token string `json:"token"`
}{}
err = json.Unmarshal(req.Params, &r) err = json.Unmarshal(req.Params, &r)
if err == nil { if err == nil {
rv, err = s.getAvailableVsCurrencies(r.Timestamp, r.Token) rv, err = s.getAvailableVsCurrencies(r.Timestamp, r.Token)
@ -456,7 +408,7 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *webs
}, },
} }
func (s *WebsocketServer) onRequest(c *websocketChannel, req *websocketReq) { func (s *WebsocketServer) onRequest(c *websocketChannel, req *WsReq) {
var err error var err error
var data interface{} var data interface{}
defer func() { defer func() {
@ -469,7 +421,7 @@ func (s *WebsocketServer) onRequest(c *websocketChannel, req *websocketReq) {
} }
// nil data means no response // nil data means no response
if data != nil { if data != nil {
c.DataOut(&websocketRes{ c.DataOut(&WsRes{
ID: req.ID, ID: req.ID,
Data: data, Data: data,
}) })
@ -499,21 +451,8 @@ func (s *WebsocketServer) onRequest(c *websocketChannel, req *websocketReq) {
} }
} }
type accountInfoReq struct { func unmarshalGetAccountInfoRequest(params []byte) (*WsAccountInfoReq, error) {
Descriptor string `json:"descriptor"` var r WsAccountInfoReq
Details string `json:"details"`
Tokens string `json:"tokens"`
PageSize int `json:"pageSize"`
Page int `json:"page"`
FromHeight int `json:"from"`
ToHeight int `json:"to"`
ContractFilter string `json:"contractFilter"`
SecondaryCurrency string `json:"secondaryCurrency"`
Gap int `json:"gap"`
}
func unmarshalGetAccountInfoRequest(params []byte) (*accountInfoReq, error) {
var r accountInfoReq
err := json.Unmarshal(params, &r) err := json.Unmarshal(params, &r)
if err != nil { if err != nil {
return nil, err return nil, err
@ -521,7 +460,7 @@ func unmarshalGetAccountInfoRequest(params []byte) (*accountInfoReq, error) {
return &r, nil return &r, nil
} }
func (s *WebsocketServer) getAccountInfo(req *accountInfoReq) (res *api.Address, err error) { func (s *WebsocketServer) getAccountInfo(req *WsAccountInfoReq) (res *api.Address, err error) {
var opt api.AccountDetails var opt api.AccountDetails
switch req.Details { switch req.Details {
case "tokens": case "tokens":
@ -563,7 +502,7 @@ func (s *WebsocketServer) getAccountInfo(req *accountInfoReq) (res *api.Address,
return a, nil return a, nil
} }
func (s *WebsocketServer) getAccountUtxo(descriptor string) (interface{}, error) { func (s *WebsocketServer) getAccountUtxo(descriptor string) (api.Utxos, error) {
utxo, err := s.api.GetXpubUtxo(descriptor, false, 0) utxo, err := s.api.GetXpubUtxo(descriptor, false, 0)
if err != nil { if err != nil {
return s.api.GetAddressUtxo(descriptor, false) return s.api.GetAddressUtxo(descriptor, false)
@ -571,7 +510,7 @@ func (s *WebsocketServer) getAccountUtxo(descriptor string) (interface{}, error)
return utxo, nil return utxo, nil
} }
func (s *WebsocketServer) getTransaction(txid string) (interface{}, error) { func (s *WebsocketServer) getTransaction(txid string) (*api.Tx, error) {
return s.api.GetTransaction(txid, false, false) return s.api.GetTransaction(txid, false, false)
} }
@ -579,31 +518,14 @@ func (s *WebsocketServer) getTransactionSpecific(txid string) (interface{}, erro
return s.chain.GetTransactionSpecific(&bchain.Tx{Txid: txid}) return s.chain.GetTransactionSpecific(&bchain.Tx{Txid: txid})
} }
func (s *WebsocketServer) getInfo() (interface{}, error) { func (s *WebsocketServer) getInfo() (*WsInfoRes, error) {
vi := common.GetVersionInfo() vi := common.GetVersionInfo()
bi := s.is.GetBackendInfo() bi := s.is.GetBackendInfo()
height, hash, err := s.db.GetBestBlock() height, hash, err := s.db.GetBestBlock()
if err != nil { if err != nil {
return nil, err return nil, err
} }
type backendInfo struct { return &WsInfoRes{
Version string `json:"version,omitempty"`
Subversion string `json:"subversion,omitempty"`
ConsensusVersion string `json:"consensus_version,omitempty"`
Consensus interface{} `json:"consensus,omitempty"`
}
type info struct {
Name string `json:"name"`
Shortcut string `json:"shortcut"`
Decimals int `json:"decimals"`
Version string `json:"version"`
BestHeight int `json:"bestHeight"`
BestHash string `json:"bestHash"`
Block0Hash string `json:"block0Hash"`
Testnet bool `json:"testnet"`
Backend backendInfo `json:"backend"`
}
return &info{
Name: s.is.Coin, Name: s.is.Coin,
Shortcut: s.is.CoinShortcut, Shortcut: s.is.CoinShortcut,
Decimals: s.chainParser.AmountDecimals(), Decimals: s.chainParser.AmountDecimals(),
@ -612,7 +534,7 @@ func (s *WebsocketServer) getInfo() (interface{}, error) {
Version: vi.Version, Version: vi.Version,
Block0Hash: s.block0hash, Block0Hash: s.block0hash,
Testnet: s.chain.IsTestnet(), Testnet: s.chain.IsTestnet(),
Backend: backendInfo{ Backend: WsBackendInfo{
Version: bi.Version, Version: bi.Version,
Subversion: bi.Subversion, Subversion: bi.Subversion,
ConsensusVersion: bi.ConsensusVersion, ConsensusVersion: bi.ConsensusVersion,
@ -621,15 +543,12 @@ func (s *WebsocketServer) getInfo() (interface{}, error) {
}, nil }, nil
} }
func (s *WebsocketServer) getBlockHash(height int) (interface{}, error) { func (s *WebsocketServer) getBlockHash(height int) (*WsBlockHashRes, error) {
h, err := s.db.GetBlockHash(uint32(height)) h, err := s.db.GetBlockHash(uint32(height))
if err != nil { if err != nil {
return nil, err return nil, err
} }
type hash struct { return &WsBlockHashRes{
Hash string `json:"hash"`
}
return &hash{
Hash: h, Hash: h,
}, nil }, nil
} }
@ -643,21 +562,12 @@ func (s *WebsocketServer) getBlock(id string, page, pageSize int) (interface{},
} }
func (s *WebsocketServer) estimateFee(c *websocketChannel, params []byte) (interface{}, error) { func (s *WebsocketServer) estimateFee(c *websocketChannel, params []byte) (interface{}, error) {
type estimateFeeReq struct { var r WsEstimateFeeReq
Blocks []int `json:"blocks"`
Specific map[string]interface{} `json:"specific"`
}
type estimateFeeRes struct {
FeePerTx string `json:"feePerTx,omitempty"`
FeePerUnit string `json:"feePerUnit,omitempty"`
FeeLimit string `json:"feeLimit,omitempty"`
}
var r estimateFeeReq
err := json.Unmarshal(params, &r) err := json.Unmarshal(params, &r)
if err != nil { if err != nil {
return nil, err return nil, err
} }
res := make([]estimateFeeRes, len(r.Blocks)) res := make([]WsEstimateFeeRes, len(r.Blocks))
if s.chainParser.GetChainType() == bchain.ChainEthereumType { if s.chainParser.GetChainType() == bchain.ChainEthereumType {
gas, err := s.chain.EthereumTypeEstimateGas(r.Specific) gas, err := s.chain.EthereumTypeEstimateGas(r.Specific)
if err != nil { if err != nil {
@ -729,7 +639,7 @@ type subscriptionResponseMessage struct {
Message string `json:"message"` Message string `json:"message"`
} }
func (s *WebsocketServer) subscribeNewBlock(c *websocketChannel, req *websocketReq) (res interface{}, err error) { func (s *WebsocketServer) subscribeNewBlock(c *websocketChannel, req *WsReq) (res interface{}, err error) {
s.newBlockSubscriptionsLock.Lock() s.newBlockSubscriptionsLock.Lock()
defer s.newBlockSubscriptionsLock.Unlock() defer s.newBlockSubscriptionsLock.Unlock()
s.newBlockSubscriptions[c] = req.ID s.newBlockSubscriptions[c] = req.ID
@ -745,7 +655,7 @@ func (s *WebsocketServer) unsubscribeNewBlock(c *websocketChannel) (res interfac
return &subscriptionResponse{false}, nil return &subscriptionResponse{false}, nil
} }
func (s *WebsocketServer) subscribeNewTransaction(c *websocketChannel, req *websocketReq) (res interface{}, err error) { func (s *WebsocketServer) subscribeNewTransaction(c *websocketChannel, req *WsReq) (res interface{}, err error) {
s.newTransactionSubscriptionsLock.Lock() s.newTransactionSubscriptionsLock.Lock()
defer s.newTransactionSubscriptionsLock.Unlock() defer s.newTransactionSubscriptionsLock.Unlock()
if !s.newTransactionEnabled { if !s.newTransactionEnabled {
@ -768,9 +678,7 @@ func (s *WebsocketServer) unsubscribeNewTransaction(c *websocketChannel) (res in
} }
func (s *WebsocketServer) unmarshalAddresses(params []byte) ([]string, error) { func (s *WebsocketServer) unmarshalAddresses(params []byte) ([]string, error) {
r := struct { r := WsSubscribeAddressesReq{}
Addresses []string `json:"addresses"`
}{}
err := json.Unmarshal(params, &r) err := json.Unmarshal(params, &r)
if err != nil { if err != nil {
return nil, err return nil, err
@ -804,7 +712,7 @@ func (s *WebsocketServer) doUnsubscribeAddresses(c *websocketChannel) {
c.addrDescs = nil c.addrDescs = nil
} }
func (s *WebsocketServer) subscribeAddresses(c *websocketChannel, addrDesc []string, req *websocketReq) (res interface{}, err error) { func (s *WebsocketServer) subscribeAddresses(c *websocketChannel, addrDesc []string, req *WsReq) (res interface{}, err error) {
s.addressSubscriptionsLock.Lock() s.addressSubscriptionsLock.Lock()
defer s.addressSubscriptionsLock.Unlock() defer s.addressSubscriptionsLock.Unlock()
// unsubscribe all previous subscriptions // unsubscribe all previous subscriptions
@ -847,7 +755,7 @@ func (s *WebsocketServer) doUnsubscribeFiatRates(c *websocketChannel) {
} }
// subscribeFiatRates subscribes all FiatRates subscriptions by this channel // subscribeFiatRates subscribes all FiatRates subscriptions by this channel
func (s *WebsocketServer) subscribeFiatRates(c *websocketChannel, d *fiatRatesSubscription, req *websocketReq) (res interface{}, err error) { func (s *WebsocketServer) subscribeFiatRates(c *websocketChannel, d *WsSubscribeFiatRatesReq, req *WsReq) (res interface{}, err error) {
s.fiatRatesSubscriptionsLock.Lock() s.fiatRatesSubscriptionsLock.Lock()
defer s.fiatRatesSubscriptionsLock.Unlock() defer s.fiatRatesSubscriptionsLock.Unlock()
// unsubscribe all previous subscriptions // unsubscribe all previous subscriptions
@ -891,7 +799,7 @@ func (s *WebsocketServer) onNewBlockAsync(hash string, height uint32) {
Hash: hash, Hash: hash,
} }
for c, id := range s.newBlockSubscriptions { for c, id := range s.newBlockSubscriptions {
c.DataOut(&websocketRes{ c.DataOut(&WsRes{
ID: id, ID: id,
Data: &data, Data: &data,
}) })
@ -908,7 +816,7 @@ func (s *WebsocketServer) sendOnNewTx(tx *api.Tx) {
s.newTransactionSubscriptionsLock.Lock() s.newTransactionSubscriptionsLock.Lock()
defer s.newTransactionSubscriptionsLock.Unlock() defer s.newTransactionSubscriptionsLock.Unlock()
for c, id := range s.newTransactionSubscriptions { for c, id := range s.newTransactionSubscriptions {
c.DataOut(&websocketRes{ c.DataOut(&WsRes{
ID: id, ID: id,
Data: &tx, Data: &tx,
}) })
@ -936,7 +844,7 @@ func (s *WebsocketServer) sendOnNewTxAddr(stringAddressDescriptor string, tx *ap
as, ok := s.addressSubscriptions[stringAddressDescriptor] as, ok := s.addressSubscriptions[stringAddressDescriptor]
if ok { if ok {
for c, id := range as { for c, id := range as {
c.DataOut(&websocketRes{ c.DataOut(&WsRes{
ID: id, ID: id,
Data: &data, Data: &data,
}) })
@ -1038,12 +946,12 @@ func (s *WebsocketServer) broadcastTicker(currency string, rates map[string]floa
dataWithTokens.TokenRates[token] = rate dataWithTokens.TokenRates[token] = rate
} }
} }
c.DataOut(&websocketRes{ c.DataOut(&WsRes{
ID: id, ID: id,
Data: &dataWithTokens, Data: &dataWithTokens,
}) })
} else { } else {
c.DataOut(&websocketRes{ c.DataOut(&WsRes{
ID: id, ID: id,
Data: &data, Data: &data,
}) })
@ -1063,17 +971,17 @@ func (s *WebsocketServer) OnNewFiatRatesTicker(ticker *common.CurrencyRatesTicke
s.broadcastTicker(allFiatRates, ticker.Rates, nil) s.broadcastTicker(allFiatRates, ticker.Rates, nil)
} }
func (s *WebsocketServer) getCurrentFiatRates(currencies []string, token string) (interface{}, error) { func (s *WebsocketServer) getCurrentFiatRates(currencies []string, token string) (*api.FiatTicker, error) {
ret, err := s.api.GetCurrentFiatRates(currencies, strings.ToLower(token)) ret, err := s.api.GetCurrentFiatRates(currencies, strings.ToLower(token))
return ret, err return ret, err
} }
func (s *WebsocketServer) getFiatRatesForTimestamps(timestamps []int64, currencies []string, token string) (interface{}, error) { func (s *WebsocketServer) getFiatRatesForTimestamps(timestamps []int64, currencies []string, token string) (*api.FiatTickers, error) {
ret, err := s.api.GetFiatRatesForTimestamps(timestamps, currencies, strings.ToLower(token)) ret, err := s.api.GetFiatRatesForTimestamps(timestamps, currencies, strings.ToLower(token))
return ret, err return ret, err
} }
func (s *WebsocketServer) getAvailableVsCurrencies(timestamp int64, token string) (interface{}, error) { func (s *WebsocketServer) getAvailableVsCurrencies(timestamp int64, token string) (*api.AvailableVsCurrencies, error) {
ret, err := s.api.GetAvailableVsCurrencies(timestamp, strings.ToLower(token)) ret, err := s.api.GetAvailableVsCurrencies(timestamp, strings.ToLower(token))
return ret, err return ret, err
} }

120
server/ws_types.go Normal file
View File

@ -0,0 +1,120 @@
package server
import "encoding/json"
type WsReq struct {
ID string `json:"id"`
Method string `json:"method" ts_type:"'getAccountInfo' | 'getInfo' | 'getBlockHash' | 'getAccountUtxo' | 'getBalanceHistory' | 'getTransaction' | 'getTransactionSpecific' | 'estimateFee' | 'sendTransaction' | 'subscribeNewBlock' | 'unsubscribeNewBlock' | 'subscribeNewTransaction' | 'unsubscribeNewTransaction' | 'subscribeAddresses' | 'unsubscribeAddresses' | 'subscribeFiatRates' | 'unsubscribeFiatRates' | 'ping' | 'getCurrentFiatRates' | 'getFiatRatesForTimestamps' | 'getFiatRatesTickersList'"`
Params json.RawMessage `json:"params" ts_type:"any"`
}
type WsRes struct {
ID string `json:"id"`
Data interface{} `json:"data"`
}
type WsAccountInfoReq struct {
Descriptor string `json:"descriptor"`
Details string `json:"details,omitempty" ts_type:"'basic' | 'tokens' | 'tokenBalances' | 'txids' | 'txslight' | 'txs'"`
Tokens string `json:"tokens,omitempty" ts_type:"'derived' | 'used' | 'nonzero'"`
PageSize int `json:"pageSize,omitempty"`
Page int `json:"page,omitempty"`
FromHeight int `json:"from,omitempty"`
ToHeight int `json:"to,omitempty"`
ContractFilter string `json:"contractFilter,omitempty"`
SecondaryCurrency string `json:"secondaryCurrency,omitempty"`
Gap int `json:"gap,omitempty"`
}
type WsBackendInfo struct {
Version string `json:"version,omitempty"`
Subversion string `json:"subversion,omitempty"`
ConsensusVersion string `json:"consensus_version,omitempty"`
Consensus interface{} `json:"consensus,omitempty"`
}
type WsInfoRes struct {
Name string `json:"name"`
Shortcut string `json:"shortcut"`
Decimals int `json:"decimals"`
Version string `json:"version"`
BestHeight int `json:"bestHeight"`
BestHash string `json:"bestHash"`
Block0Hash string `json:"block0Hash"`
Testnet bool `json:"testnet"`
Backend WsBackendInfo `json:"backend"`
}
type WsBlockHashReq struct {
Height int `json:"height"`
}
type WsBlockHashRes struct {
Hash string `json:"hash"`
}
type WsBlockReq struct {
Id string `json:"id"`
PageSize int `json:"pageSize,omitempty"`
Page int `json:"page,omitempty"`
}
type WsAccountUtxoReq struct {
Descriptor string `json:"descriptor"`
}
type WsBalanceHistoryReq struct {
Descriptor string `json:"descriptor"`
From int64 `json:"from,omitempty"`
To int64 `json:"to,omitempty"`
Currencies []string `json:"currencies,omitempty"`
Gap int `json:"gap,omitempty"`
GroupBy uint32 `json:"groupBy,omitempty"`
}
type WsTransactionReq struct {
Txid string `json:"txid"`
}
type WsTransactionSpecificReq struct {
Txid string `json:"txid"`
}
type WsEstimateFeeReq struct {
Blocks []int `json:"blocks,omitempty"`
Specific map[string]interface{} `json:"specific,omitempty" ts_type:"{conservative?: boolean;txsize?: number;from?: string;to?: string;data?: string;value?: string;}"`
}
type WsEstimateFeeRes struct {
FeePerTx string `json:"feePerTx,omitempty"`
FeePerUnit string `json:"feePerUnit,omitempty"`
FeeLimit string `json:"feeLimit,omitempty"`
}
type WsSendTransactionReq struct {
Hex string `json:"hex"`
}
type WsSubscribeAddressesReq struct {
Addresses []string `json:"addresses"`
}
type WsSubscribeFiatRatesReq struct {
Currency string `json:"currency,omitempty"`
Tokens []string `json:"tokens,omitempty"`
}
type WsCurrentFiatRatesReq struct {
Currencies []string `json:"currencies,omitempty"`
Token string `json:"token,omitempty"`
}
type WsFiatRatesForTimestampsReq struct {
Timestamps []int64 `json:"timestamps"`
Currencies []string `json:"currencies,omitempty"`
Token string `json:"token,omitempty"`
}
type WsFiatRatesTickersListReq struct {
Timestamp int64 `json:"timestamp,omitempty"`
Token string `json:"token,omitempty"`
}