Add generatetoaddress and estimatesmartfee RPCs

This commit is contained in:
Torkel Rogstad 2019-11-26 14:33:48 +01:00 committed by John C. Vernaleo
parent a8eadd2ce4
commit 8b1be46463
7 changed files with 179 additions and 0 deletions

View file

@ -59,6 +59,23 @@ func NewDebugLevelCmd(levelSpec string) *DebugLevelCmd {
} }
} }
// GenerateToAddressCmd defines the generatetoaddress JSON-RPC command.
type GenerateToAddressCmd struct {
NumBlocks int64
Address string
MaxTries *int64 `jsonrpcdefault:"1000000"`
}
// NewGenerateToAddressCmd returns a new instance which can be used to issue a
// generatetoaddress JSON-RPC command.
func NewGenerateToAddressCmd(numBlocks int64, address string, maxTries *int64) *GenerateToAddressCmd {
return &GenerateToAddressCmd{
NumBlocks: numBlocks,
Address: address,
MaxTries: maxTries,
}
}
// GenerateCmd defines the generate JSON-RPC command. // GenerateCmd defines the generate JSON-RPC command.
type GenerateCmd struct { type GenerateCmd struct {
NumBlocks uint32 NumBlocks uint32
@ -131,6 +148,7 @@ func init() {
MustRegisterCmd("debuglevel", (*DebugLevelCmd)(nil), flags) MustRegisterCmd("debuglevel", (*DebugLevelCmd)(nil), flags)
MustRegisterCmd("node", (*NodeCmd)(nil), flags) MustRegisterCmd("node", (*NodeCmd)(nil), flags)
MustRegisterCmd("generate", (*GenerateCmd)(nil), flags) MustRegisterCmd("generate", (*GenerateCmd)(nil), flags)
MustRegisterCmd("generatetoaddress", (*GenerateToAddressCmd)(nil), flags)
MustRegisterCmd("getbestblock", (*GetBestBlockCmd)(nil), flags) MustRegisterCmd("getbestblock", (*GetBestBlockCmd)(nil), flags)
MustRegisterCmd("getcurrentnet", (*GetCurrentNetCmd)(nil), flags) MustRegisterCmd("getcurrentnet", (*GetCurrentNetCmd)(nil), flags)
MustRegisterCmd("getheaders", (*GetHeadersCmd)(nil), flags) MustRegisterCmd("getheaders", (*GetHeadersCmd)(nil), flags)

View file

@ -114,6 +114,24 @@ func TestBtcdExtCmds(t *testing.T) {
NumBlocks: 1, NumBlocks: 1,
}, },
}, },
{
name: "generatetoaddress",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("generatetoaddress", 1, "1Address")
},
staticCmd: func() interface{} {
return btcjson.NewGenerateToAddressCmd(1, "1Address", nil)
},
marshalled: `{"jsonrpc":"1.0","method":"generatetoaddress","params":[1,"1Address"],"id":1}`,
unmarshalled: &btcjson.GenerateToAddressCmd{
NumBlocks: 1,
Address: "1Address",
MaxTries: func() *int64 {
var i int64 = 1000000
return &i
}(),
},
},
{ {
name: "getbestblock", name: "getbestblock",
newCmd: func() (interface{}, error) { newCmd: func() (interface{}, error) {

View file

@ -624,3 +624,11 @@ type ValidateAddressChainResult struct {
IsValid bool `json:"isvalid"` IsValid bool `json:"isvalid"`
Address string `json:"address,omitempty"` Address string `json:"address,omitempty"`
} }
// EstimateSmartFeeResult models the data returned buy the chain server
// estimatesmartfee command
type EstimateSmartFeeResult struct {
FeeRate *float64 `json:"feerate,omitempty"`
Errors []string `json:"errors,omitempty"`
Blocks int64 `json:"blocks"`
}

View file

@ -81,6 +81,30 @@ func NewEncryptWalletCmd(passphrase string) *EncryptWalletCmd {
} }
} }
// EstimateSmartFeeMode defines the different fee estimation modes available
// for the estimatesmartfee JSON-RPC command.
type EstimateSmartFeeMode string
var (
EstimateModeUnset EstimateSmartFeeMode = "UNSET"
EstimateModeEconomical EstimateSmartFeeMode = "ECONOMICAL"
EstimateModeConservative EstimateSmartFeeMode = "CONSERVATIVE"
)
// EstimateSmartFeeCmd defines the estimatesmartfee JSON-RPC command.
type EstimateSmartFeeCmd struct {
ConfTarget int64
EstimateMode *EstimateSmartFeeMode `jsonrpcdefault:"\"CONSERVATIVE\""`
}
// NewEstimateSmartFeeCmd returns a new instance which can be used to issue a
// estimatesmartfee JSON-RPC command.
func NewEstimateSmartFeeCmd(confTarget int64, mode *EstimateSmartFeeMode) *EstimateSmartFeeCmd {
return &EstimateSmartFeeCmd{
ConfTarget: confTarget, EstimateMode: mode,
}
}
// EstimateFeeCmd defines the estimatefee JSON-RPC command. // EstimateFeeCmd defines the estimatefee JSON-RPC command.
type EstimateFeeCmd struct { type EstimateFeeCmd struct {
NumBlocks int64 NumBlocks int64
@ -662,6 +686,7 @@ func init() {
MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags) MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags)
MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags) MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags)
MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags) MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags)
MustRegisterCmd("estimatesmartfee", (*EstimateSmartFeeCmd)(nil), flags)
MustRegisterCmd("estimatefee", (*EstimateFeeCmd)(nil), flags) MustRegisterCmd("estimatefee", (*EstimateFeeCmd)(nil), flags)
MustRegisterCmd("estimatepriority", (*EstimatePriorityCmd)(nil), flags) MustRegisterCmd("estimatepriority", (*EstimatePriorityCmd)(nil), flags)
MustRegisterCmd("getaccount", (*GetAccountCmd)(nil), flags) MustRegisterCmd("getaccount", (*GetAccountCmd)(nil), flags)

View file

@ -128,6 +128,34 @@ func TestWalletSvrCmds(t *testing.T) {
NumBlocks: 6, NumBlocks: 6,
}, },
}, },
{
name: "estimatesmartfee - no mode",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("estimatesmartfee", 6)
},
staticCmd: func() interface{} {
return btcjson.NewEstimateSmartFeeCmd(6, nil)
},
marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6],"id":1}`,
unmarshalled: &btcjson.EstimateSmartFeeCmd{
ConfTarget: 6,
EstimateMode: &btcjson.EstimateModeConservative,
},
},
{
name: "estimatesmartfee - economical mode",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("estimatesmartfee", 6, btcjson.EstimateModeEconomical)
},
staticCmd: func() interface{} {
return btcjson.NewEstimateSmartFeeCmd(6, &btcjson.EstimateModeEconomical)
},
marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6,"ECONOMICAL"],"id":1}`,
unmarshalled: &btcjson.EstimateSmartFeeCmd{
ConfTarget: 6,
EstimateMode: &btcjson.EstimateModeEconomical,
},
},
{ {
name: "estimatepriority", name: "estimatepriority",
newCmd: func() (interface{}, error) { newCmd: func() (interface{}, error) {

View file

@ -669,6 +669,41 @@ func (c *Client) EstimateFee(numBlocks int64) (float64, error) {
return c.EstimateFeeAsync(numBlocks).Receive() return c.EstimateFeeAsync(numBlocks).Receive()
} }
// FutureEstimateFeeResult is a future promise to deliver the result of a
// EstimateSmartFeeAsync RPC invocation (or an applicable error).
type FutureEstimateSmartFeeResult chan *response
// Receive waits for the response promised by the future and returns the
// estimated fee.
func (r FutureEstimateSmartFeeResult) Receive() (*btcjson.EstimateSmartFeeResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
var verified btcjson.EstimateSmartFeeResult
err = json.Unmarshal(res, &verified)
if err != nil {
return nil, err
}
return &verified, nil
}
// EstimateSmartFeeAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See EstimateSmartFee for the blocking version and more details.
func (c *Client) EstimateSmartFeeAsync(confTarget int64, mode *btcjson.EstimateSmartFeeMode) FutureEstimateSmartFeeResult {
cmd := btcjson.NewEstimateSmartFeeCmd(confTarget, mode)
return c.sendCmd(cmd)
}
// EstimateSmartFee requests the server to estimate a fee level based on the given parameters.
func (c *Client) EstimateSmartFee(confTarget int64, mode *btcjson.EstimateSmartFeeMode) (*btcjson.EstimateSmartFeeResult, error) {
return c.EstimateSmartFeeAsync(confTarget, mode).Receive()
}
// FutureVerifyChainResult is a future promise to deliver the result of a // FutureVerifyChainResult is a future promise to deliver the result of a
// VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync // VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync
// invocation (or an applicable error). // invocation (or an applicable error).

View file

@ -61,6 +61,53 @@ func (c *Client) Generate(numBlocks uint32) ([]*chainhash.Hash, error) {
return c.GenerateAsync(numBlocks).Receive() return c.GenerateAsync(numBlocks).Receive()
} }
// FutureGenerateToAddressResult is a future promise to deliver the result of a
// GenerateToAddressResult RPC invocation (or an applicable error).
type FutureGenerateToAddressResult chan *response
// Receive waits for the response promised by the future and returns the hashes of
// of the generated blocks.
func (f FutureGenerateToAddressResult) Receive() ([]*chainhash.Hash, error) {
res, err := receiveFuture(f)
if err != nil {
return nil, err
}
// Unmarshal result as a list of strings.
var result []string
err = json.Unmarshal(res, &result)
if err != nil {
return nil, err
}
// Convert each block hash to a chainhash.Hash and store a pointer to
// each.
convertedResult := make([]*chainhash.Hash, len(result))
for i, hashString := range result {
convertedResult[i], err = chainhash.NewHashFromStr(hashString)
if err != nil {
return nil, err
}
}
return convertedResult, nil
}
// GenerateToAddressAsync returns an instance of a type that can be used to get
// the result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See GenerateToAddress for the blocking version and more details.
func (c *Client) GenerateToAddressAsync(numBlocks int64, address btcutil.Address, maxTries *int64) FutureGenerateToAddressResult {
cmd := btcjson.NewGenerateToAddressCmd(numBlocks, address.EncodeAddress(), maxTries)
return c.sendCmd(cmd)
}
// GenerateToAddress generates numBlocks blocks to the given address and returns their hashes.
func (c *Client) GenerateToAddress(numBlocks int64, address btcutil.Address, maxTries *int64) ([]*chainhash.Hash, error) {
return c.GenerateToAddressAsync(numBlocks, address, maxTries).Receive()
}
// FutureGetGenerateResult is a future promise to deliver the result of a // FutureGetGenerateResult is a future promise to deliver the result of a
// GetGenerateAsync RPC invocation (or an applicable error). // GetGenerateAsync RPC invocation (or an applicable error).
type FutureGetGenerateResult chan *response type FutureGetGenerateResult chan *response