github.com/btcsuite/btcd@v0.24.0/btcjson/walletsvrcmds_test.go (about)

     1  // Copyright (c) 2014-2020 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package btcjson_test
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/json"
    10  	"fmt"
    11  	"reflect"
    12  	"testing"
    13  
    14  	"github.com/btcsuite/btcd/btcjson"
    15  	"github.com/btcsuite/btcd/btcutil"
    16  )
    17  
    18  // TestWalletSvrCmds tests all of the wallet server commands marshal and
    19  // unmarshal into valid results include handling of optional fields being
    20  // omitted in the marshalled command, while optional fields with defaults have
    21  // the default assigned on unmarshalled commands.
    22  func TestWalletSvrCmds(t *testing.T) {
    23  	t.Parallel()
    24  
    25  	testID := int(1)
    26  	tests := []struct {
    27  		name         string
    28  		newCmd       func() (interface{}, error)
    29  		staticCmd    func() interface{}
    30  		marshalled   string
    31  		unmarshalled interface{}
    32  	}{
    33  		{
    34  			name: "addmultisigaddress",
    35  			newCmd: func() (interface{}, error) {
    36  				return btcjson.NewCmd("addmultisigaddress", 2, []string{"031234", "035678"})
    37  			},
    38  			staticCmd: func() interface{} {
    39  				keys := []string{"031234", "035678"}
    40  				return btcjson.NewAddMultisigAddressCmd(2, keys, nil)
    41  			},
    42  			marshalled: `{"jsonrpc":"1.0","method":"addmultisigaddress","params":[2,["031234","035678"]],"id":1}`,
    43  			unmarshalled: &btcjson.AddMultisigAddressCmd{
    44  				NRequired: 2,
    45  				Keys:      []string{"031234", "035678"},
    46  				Account:   nil,
    47  			},
    48  		},
    49  		{
    50  			name: "addmultisigaddress optional",
    51  			newCmd: func() (interface{}, error) {
    52  				return btcjson.NewCmd("addmultisigaddress", 2, []string{"031234", "035678"}, "test")
    53  			},
    54  			staticCmd: func() interface{} {
    55  				keys := []string{"031234", "035678"}
    56  				return btcjson.NewAddMultisigAddressCmd(2, keys, btcjson.String("test"))
    57  			},
    58  			marshalled: `{"jsonrpc":"1.0","method":"addmultisigaddress","params":[2,["031234","035678"],"test"],"id":1}`,
    59  			unmarshalled: &btcjson.AddMultisigAddressCmd{
    60  				NRequired: 2,
    61  				Keys:      []string{"031234", "035678"},
    62  				Account:   btcjson.String("test"),
    63  			},
    64  		},
    65  		{
    66  			name: "createwallet",
    67  			newCmd: func() (interface{}, error) {
    68  				return btcjson.NewCmd("createwallet", "mywallet", true, true, "secret", true)
    69  			},
    70  			staticCmd: func() interface{} {
    71  				return btcjson.NewCreateWalletCmd("mywallet",
    72  					btcjson.Bool(true), btcjson.Bool(true),
    73  					btcjson.String("secret"), btcjson.Bool(true))
    74  			},
    75  			marshalled: `{"jsonrpc":"1.0","method":"createwallet","params":["mywallet",true,true,"secret",true],"id":1}`,
    76  			unmarshalled: &btcjson.CreateWalletCmd{
    77  				WalletName:         "mywallet",
    78  				DisablePrivateKeys: btcjson.Bool(true),
    79  				Blank:              btcjson.Bool(true),
    80  				Passphrase:         btcjson.String("secret"),
    81  				AvoidReuse:         btcjson.Bool(true),
    82  			},
    83  		},
    84  		{
    85  			name: "createwallet - optional1",
    86  			newCmd: func() (interface{}, error) {
    87  				return btcjson.NewCmd("createwallet", "mywallet")
    88  			},
    89  			staticCmd: func() interface{} {
    90  				return btcjson.NewCreateWalletCmd("mywallet",
    91  					nil, nil, nil, nil)
    92  			},
    93  			marshalled: `{"jsonrpc":"1.0","method":"createwallet","params":["mywallet"],"id":1}`,
    94  			unmarshalled: &btcjson.CreateWalletCmd{
    95  				WalletName:         "mywallet",
    96  				DisablePrivateKeys: btcjson.Bool(false),
    97  				Blank:              btcjson.Bool(false),
    98  				Passphrase:         btcjson.String(""),
    99  				AvoidReuse:         btcjson.Bool(false),
   100  			},
   101  		},
   102  		{
   103  			name: "createwallet - optional2",
   104  			newCmd: func() (interface{}, error) {
   105  				return btcjson.NewCmd("createwallet", "mywallet", "null", "null", "secret")
   106  			},
   107  			staticCmd: func() interface{} {
   108  				return btcjson.NewCreateWalletCmd("mywallet",
   109  					nil, nil, btcjson.String("secret"), nil)
   110  			},
   111  			marshalled: `{"jsonrpc":"1.0","method":"createwallet","params":["mywallet",null,null,"secret"],"id":1}`,
   112  			unmarshalled: &btcjson.CreateWalletCmd{
   113  				WalletName:         "mywallet",
   114  				DisablePrivateKeys: nil,
   115  				Blank:              nil,
   116  				Passphrase:         btcjson.String("secret"),
   117  				AvoidReuse:         btcjson.Bool(false),
   118  			},
   119  		},
   120  		{
   121  			name: "addwitnessaddress",
   122  			newCmd: func() (interface{}, error) {
   123  				return btcjson.NewCmd("addwitnessaddress", "1address")
   124  			},
   125  			staticCmd: func() interface{} {
   126  				return btcjson.NewAddWitnessAddressCmd("1address")
   127  			},
   128  			marshalled: `{"jsonrpc":"1.0","method":"addwitnessaddress","params":["1address"],"id":1}`,
   129  			unmarshalled: &btcjson.AddWitnessAddressCmd{
   130  				Address: "1address",
   131  			},
   132  		},
   133  		{
   134  			name: "backupwallet",
   135  			newCmd: func() (interface{}, error) {
   136  				return btcjson.NewCmd("backupwallet", "backup.dat")
   137  			},
   138  			staticCmd: func() interface{} {
   139  				return btcjson.NewBackupWalletCmd("backup.dat")
   140  			},
   141  			marshalled:   `{"jsonrpc":"1.0","method":"backupwallet","params":["backup.dat"],"id":1}`,
   142  			unmarshalled: &btcjson.BackupWalletCmd{Destination: "backup.dat"},
   143  		},
   144  		{
   145  			name: "loadwallet",
   146  			newCmd: func() (interface{}, error) {
   147  				return btcjson.NewCmd("loadwallet", "wallet.dat")
   148  			},
   149  			staticCmd: func() interface{} {
   150  				return btcjson.NewLoadWalletCmd("wallet.dat")
   151  			},
   152  			marshalled:   `{"jsonrpc":"1.0","method":"loadwallet","params":["wallet.dat"],"id":1}`,
   153  			unmarshalled: &btcjson.LoadWalletCmd{WalletName: "wallet.dat"},
   154  		},
   155  		{
   156  			name: "unloadwallet",
   157  			newCmd: func() (interface{}, error) {
   158  				return btcjson.NewCmd("unloadwallet", "default")
   159  			},
   160  			staticCmd: func() interface{} {
   161  				return btcjson.NewUnloadWalletCmd(btcjson.String("default"))
   162  			},
   163  			marshalled:   `{"jsonrpc":"1.0","method":"unloadwallet","params":["default"],"id":1}`,
   164  			unmarshalled: &btcjson.UnloadWalletCmd{WalletName: btcjson.String("default")},
   165  		},
   166  		{name: "unloadwallet - nil arg",
   167  			newCmd: func() (interface{}, error) {
   168  				return btcjson.NewCmd("unloadwallet")
   169  			},
   170  			staticCmd: func() interface{} {
   171  				return btcjson.NewUnloadWalletCmd(nil)
   172  			},
   173  			marshalled:   `{"jsonrpc":"1.0","method":"unloadwallet","params":[],"id":1}`,
   174  			unmarshalled: &btcjson.UnloadWalletCmd{WalletName: nil},
   175  		},
   176  		{
   177  			name: "createmultisig",
   178  			newCmd: func() (interface{}, error) {
   179  				return btcjson.NewCmd("createmultisig", 2, []string{"031234", "035678"})
   180  			},
   181  			staticCmd: func() interface{} {
   182  				keys := []string{"031234", "035678"}
   183  				return btcjson.NewCreateMultisigCmd(2, keys)
   184  			},
   185  			marshalled: `{"jsonrpc":"1.0","method":"createmultisig","params":[2,["031234","035678"]],"id":1}`,
   186  			unmarshalled: &btcjson.CreateMultisigCmd{
   187  				NRequired: 2,
   188  				Keys:      []string{"031234", "035678"},
   189  			},
   190  		},
   191  		{
   192  			name: "dumpprivkey",
   193  			newCmd: func() (interface{}, error) {
   194  				return btcjson.NewCmd("dumpprivkey", "1Address")
   195  			},
   196  			staticCmd: func() interface{} {
   197  				return btcjson.NewDumpPrivKeyCmd("1Address")
   198  			},
   199  			marshalled: `{"jsonrpc":"1.0","method":"dumpprivkey","params":["1Address"],"id":1}`,
   200  			unmarshalled: &btcjson.DumpPrivKeyCmd{
   201  				Address: "1Address",
   202  			},
   203  		},
   204  		{
   205  			name: "encryptwallet",
   206  			newCmd: func() (interface{}, error) {
   207  				return btcjson.NewCmd("encryptwallet", "pass")
   208  			},
   209  			staticCmd: func() interface{} {
   210  				return btcjson.NewEncryptWalletCmd("pass")
   211  			},
   212  			marshalled: `{"jsonrpc":"1.0","method":"encryptwallet","params":["pass"],"id":1}`,
   213  			unmarshalled: &btcjson.EncryptWalletCmd{
   214  				Passphrase: "pass",
   215  			},
   216  		},
   217  		{
   218  			name: "estimatefee",
   219  			newCmd: func() (interface{}, error) {
   220  				return btcjson.NewCmd("estimatefee", 6)
   221  			},
   222  			staticCmd: func() interface{} {
   223  				return btcjson.NewEstimateFeeCmd(6)
   224  			},
   225  			marshalled: `{"jsonrpc":"1.0","method":"estimatefee","params":[6],"id":1}`,
   226  			unmarshalled: &btcjson.EstimateFeeCmd{
   227  				NumBlocks: 6,
   228  			},
   229  		},
   230  		{
   231  			name: "estimatesmartfee - no mode",
   232  			newCmd: func() (interface{}, error) {
   233  				return btcjson.NewCmd("estimatesmartfee", 6)
   234  			},
   235  			staticCmd: func() interface{} {
   236  				return btcjson.NewEstimateSmartFeeCmd(6, nil)
   237  			},
   238  			marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6],"id":1}`,
   239  			unmarshalled: &btcjson.EstimateSmartFeeCmd{
   240  				ConfTarget:   6,
   241  				EstimateMode: &btcjson.EstimateModeConservative,
   242  			},
   243  		},
   244  		{
   245  			name: "estimatesmartfee - economical mode",
   246  			newCmd: func() (interface{}, error) {
   247  				return btcjson.NewCmd("estimatesmartfee", 6, btcjson.EstimateModeEconomical)
   248  			},
   249  			staticCmd: func() interface{} {
   250  				return btcjson.NewEstimateSmartFeeCmd(6, &btcjson.EstimateModeEconomical)
   251  			},
   252  			marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6,"ECONOMICAL"],"id":1}`,
   253  			unmarshalled: &btcjson.EstimateSmartFeeCmd{
   254  				ConfTarget:   6,
   255  				EstimateMode: &btcjson.EstimateModeEconomical,
   256  			},
   257  		},
   258  		{
   259  			name: "estimatepriority",
   260  			newCmd: func() (interface{}, error) {
   261  				return btcjson.NewCmd("estimatepriority", 6)
   262  			},
   263  			staticCmd: func() interface{} {
   264  				return btcjson.NewEstimatePriorityCmd(6)
   265  			},
   266  			marshalled: `{"jsonrpc":"1.0","method":"estimatepriority","params":[6],"id":1}`,
   267  			unmarshalled: &btcjson.EstimatePriorityCmd{
   268  				NumBlocks: 6,
   269  			},
   270  		},
   271  		{
   272  			name: "getaccount",
   273  			newCmd: func() (interface{}, error) {
   274  				return btcjson.NewCmd("getaccount", "1Address")
   275  			},
   276  			staticCmd: func() interface{} {
   277  				return btcjson.NewGetAccountCmd("1Address")
   278  			},
   279  			marshalled: `{"jsonrpc":"1.0","method":"getaccount","params":["1Address"],"id":1}`,
   280  			unmarshalled: &btcjson.GetAccountCmd{
   281  				Address: "1Address",
   282  			},
   283  		},
   284  		{
   285  			name: "getaccountaddress",
   286  			newCmd: func() (interface{}, error) {
   287  				return btcjson.NewCmd("getaccountaddress", "acct")
   288  			},
   289  			staticCmd: func() interface{} {
   290  				return btcjson.NewGetAccountAddressCmd("acct")
   291  			},
   292  			marshalled: `{"jsonrpc":"1.0","method":"getaccountaddress","params":["acct"],"id":1}`,
   293  			unmarshalled: &btcjson.GetAccountAddressCmd{
   294  				Account: "acct",
   295  			},
   296  		},
   297  		{
   298  			name: "getaddressesbyaccount",
   299  			newCmd: func() (interface{}, error) {
   300  				return btcjson.NewCmd("getaddressesbyaccount", "acct")
   301  			},
   302  			staticCmd: func() interface{} {
   303  				return btcjson.NewGetAddressesByAccountCmd("acct")
   304  			},
   305  			marshalled: `{"jsonrpc":"1.0","method":"getaddressesbyaccount","params":["acct"],"id":1}`,
   306  			unmarshalled: &btcjson.GetAddressesByAccountCmd{
   307  				Account: "acct",
   308  			},
   309  		},
   310  		{
   311  			name: "getaddressinfo",
   312  			newCmd: func() (interface{}, error) {
   313  				return btcjson.NewCmd("getaddressinfo", "1234")
   314  			},
   315  			staticCmd: func() interface{} {
   316  				return btcjson.NewGetAddressInfoCmd("1234")
   317  			},
   318  			marshalled: `{"jsonrpc":"1.0","method":"getaddressinfo","params":["1234"],"id":1}`,
   319  			unmarshalled: &btcjson.GetAddressInfoCmd{
   320  				Address: "1234",
   321  			},
   322  		},
   323  		{
   324  			name: "getbalance",
   325  			newCmd: func() (interface{}, error) {
   326  				return btcjson.NewCmd("getbalance")
   327  			},
   328  			staticCmd: func() interface{} {
   329  				return btcjson.NewGetBalanceCmd(nil, nil)
   330  			},
   331  			marshalled: `{"jsonrpc":"1.0","method":"getbalance","params":[],"id":1}`,
   332  			unmarshalled: &btcjson.GetBalanceCmd{
   333  				Account: nil,
   334  				MinConf: btcjson.Int(1),
   335  			},
   336  		},
   337  		{
   338  			name: "getbalance optional1",
   339  			newCmd: func() (interface{}, error) {
   340  				return btcjson.NewCmd("getbalance", "acct")
   341  			},
   342  			staticCmd: func() interface{} {
   343  				return btcjson.NewGetBalanceCmd(btcjson.String("acct"), nil)
   344  			},
   345  			marshalled: `{"jsonrpc":"1.0","method":"getbalance","params":["acct"],"id":1}`,
   346  			unmarshalled: &btcjson.GetBalanceCmd{
   347  				Account: btcjson.String("acct"),
   348  				MinConf: btcjson.Int(1),
   349  			},
   350  		},
   351  		{
   352  			name: "getbalance optional2",
   353  			newCmd: func() (interface{}, error) {
   354  				return btcjson.NewCmd("getbalance", "acct", 6)
   355  			},
   356  			staticCmd: func() interface{} {
   357  				return btcjson.NewGetBalanceCmd(btcjson.String("acct"), btcjson.Int(6))
   358  			},
   359  			marshalled: `{"jsonrpc":"1.0","method":"getbalance","params":["acct",6],"id":1}`,
   360  			unmarshalled: &btcjson.GetBalanceCmd{
   361  				Account: btcjson.String("acct"),
   362  				MinConf: btcjson.Int(6),
   363  			},
   364  		},
   365  		{
   366  			name: "getbalances",
   367  			newCmd: func() (interface{}, error) {
   368  				return btcjson.NewCmd("getbalances")
   369  			},
   370  			staticCmd: func() interface{} {
   371  				return btcjson.NewGetBalancesCmd()
   372  			},
   373  			marshalled:   `{"jsonrpc":"1.0","method":"getbalances","params":[],"id":1}`,
   374  			unmarshalled: &btcjson.GetBalancesCmd{},
   375  		},
   376  		{
   377  			name: "getnewaddress",
   378  			newCmd: func() (interface{}, error) {
   379  				return btcjson.NewCmd("getnewaddress")
   380  			},
   381  			staticCmd: func() interface{} {
   382  				return btcjson.NewGetNewAddressCmd(nil, nil)
   383  			},
   384  			marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":[],"id":1}`,
   385  			unmarshalled: &btcjson.GetNewAddressCmd{
   386  				Account:     nil,
   387  				AddressType: nil,
   388  			},
   389  		},
   390  		{
   391  			name: "getnewaddress optional acct",
   392  			newCmd: func() (interface{}, error) {
   393  				return btcjson.NewCmd("getnewaddress", "acct")
   394  			},
   395  			staticCmd: func() interface{} {
   396  				return btcjson.NewGetNewAddressCmd(btcjson.String("acct"), nil)
   397  			},
   398  			marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":["acct"],"id":1}`,
   399  			unmarshalled: &btcjson.GetNewAddressCmd{
   400  				Account:     btcjson.String("acct"),
   401  				AddressType: nil,
   402  			},
   403  		},
   404  		{
   405  			name: "getnewaddress optional acct and type",
   406  			newCmd: func() (interface{}, error) {
   407  				return btcjson.NewCmd("getnewaddress", "acct", "legacy")
   408  			},
   409  			staticCmd: func() interface{} {
   410  				return btcjson.NewGetNewAddressCmd(btcjson.String("acct"), btcjson.String("legacy"))
   411  			},
   412  			marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":["acct","legacy"],"id":1}`,
   413  			unmarshalled: &btcjson.GetNewAddressCmd{
   414  				Account:     btcjson.String("acct"),
   415  				AddressType: btcjson.String("legacy"),
   416  			},
   417  		},
   418  		{
   419  			name: "getrawchangeaddress",
   420  			newCmd: func() (interface{}, error) {
   421  				return btcjson.NewCmd("getrawchangeaddress")
   422  			},
   423  			staticCmd: func() interface{} {
   424  				return btcjson.NewGetRawChangeAddressCmd(nil, nil)
   425  			},
   426  			marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":[],"id":1}`,
   427  			unmarshalled: &btcjson.GetRawChangeAddressCmd{
   428  				Account:     nil,
   429  				AddressType: nil,
   430  			},
   431  		},
   432  		{
   433  			name: "getrawchangeaddress optional acct",
   434  			newCmd: func() (interface{}, error) {
   435  				return btcjson.NewCmd("getrawchangeaddress", "acct")
   436  			},
   437  			staticCmd: func() interface{} {
   438  				return btcjson.NewGetRawChangeAddressCmd(btcjson.String("acct"), nil)
   439  			},
   440  			marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":["acct"],"id":1}`,
   441  			unmarshalled: &btcjson.GetRawChangeAddressCmd{
   442  				Account:     btcjson.String("acct"),
   443  				AddressType: nil,
   444  			},
   445  		},
   446  		{
   447  			name: "getrawchangeaddress optional acct and type",
   448  			newCmd: func() (interface{}, error) {
   449  				return btcjson.NewCmd("getrawchangeaddress", "acct", "legacy")
   450  			},
   451  			staticCmd: func() interface{} {
   452  				return btcjson.NewGetRawChangeAddressCmd(btcjson.String("acct"), btcjson.String("legacy"))
   453  			},
   454  			marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":["acct","legacy"],"id":1}`,
   455  			unmarshalled: &btcjson.GetRawChangeAddressCmd{
   456  				Account:     btcjson.String("acct"),
   457  				AddressType: btcjson.String("legacy"),
   458  			},
   459  		},
   460  		{
   461  			name: "getreceivedbyaccount",
   462  			newCmd: func() (interface{}, error) {
   463  				return btcjson.NewCmd("getreceivedbyaccount", "acct")
   464  			},
   465  			staticCmd: func() interface{} {
   466  				return btcjson.NewGetReceivedByAccountCmd("acct", nil)
   467  			},
   468  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaccount","params":["acct"],"id":1}`,
   469  			unmarshalled: &btcjson.GetReceivedByAccountCmd{
   470  				Account: "acct",
   471  				MinConf: btcjson.Int(1),
   472  			},
   473  		},
   474  		{
   475  			name: "getreceivedbyaccount optional",
   476  			newCmd: func() (interface{}, error) {
   477  				return btcjson.NewCmd("getreceivedbyaccount", "acct", 6)
   478  			},
   479  			staticCmd: func() interface{} {
   480  				return btcjson.NewGetReceivedByAccountCmd("acct", btcjson.Int(6))
   481  			},
   482  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaccount","params":["acct",6],"id":1}`,
   483  			unmarshalled: &btcjson.GetReceivedByAccountCmd{
   484  				Account: "acct",
   485  				MinConf: btcjson.Int(6),
   486  			},
   487  		},
   488  		{
   489  			name: "getreceivedbyaddress",
   490  			newCmd: func() (interface{}, error) {
   491  				return btcjson.NewCmd("getreceivedbyaddress", "1Address")
   492  			},
   493  			staticCmd: func() interface{} {
   494  				return btcjson.NewGetReceivedByAddressCmd("1Address", nil)
   495  			},
   496  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaddress","params":["1Address"],"id":1}`,
   497  			unmarshalled: &btcjson.GetReceivedByAddressCmd{
   498  				Address: "1Address",
   499  				MinConf: btcjson.Int(1),
   500  			},
   501  		},
   502  		{
   503  			name: "getreceivedbyaddress optional",
   504  			newCmd: func() (interface{}, error) {
   505  				return btcjson.NewCmd("getreceivedbyaddress", "1Address", 6)
   506  			},
   507  			staticCmd: func() interface{} {
   508  				return btcjson.NewGetReceivedByAddressCmd("1Address", btcjson.Int(6))
   509  			},
   510  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaddress","params":["1Address",6],"id":1}`,
   511  			unmarshalled: &btcjson.GetReceivedByAddressCmd{
   512  				Address: "1Address",
   513  				MinConf: btcjson.Int(6),
   514  			},
   515  		},
   516  		{
   517  			name: "gettransaction",
   518  			newCmd: func() (interface{}, error) {
   519  				return btcjson.NewCmd("gettransaction", "123")
   520  			},
   521  			staticCmd: func() interface{} {
   522  				return btcjson.NewGetTransactionCmd("123", nil)
   523  			},
   524  			marshalled: `{"jsonrpc":"1.0","method":"gettransaction","params":["123"],"id":1}`,
   525  			unmarshalled: &btcjson.GetTransactionCmd{
   526  				Txid:             "123",
   527  				IncludeWatchOnly: btcjson.Bool(false),
   528  			},
   529  		},
   530  		{
   531  			name: "gettransaction optional",
   532  			newCmd: func() (interface{}, error) {
   533  				return btcjson.NewCmd("gettransaction", "123", true)
   534  			},
   535  			staticCmd: func() interface{} {
   536  				return btcjson.NewGetTransactionCmd("123", btcjson.Bool(true))
   537  			},
   538  			marshalled: `{"jsonrpc":"1.0","method":"gettransaction","params":["123",true],"id":1}`,
   539  			unmarshalled: &btcjson.GetTransactionCmd{
   540  				Txid:             "123",
   541  				IncludeWatchOnly: btcjson.Bool(true),
   542  			},
   543  		},
   544  		{
   545  			name: "getwalletinfo",
   546  			newCmd: func() (interface{}, error) {
   547  				return btcjson.NewCmd("getwalletinfo")
   548  			},
   549  			staticCmd: func() interface{} {
   550  				return btcjson.NewGetWalletInfoCmd()
   551  			},
   552  			marshalled:   `{"jsonrpc":"1.0","method":"getwalletinfo","params":[],"id":1}`,
   553  			unmarshalled: &btcjson.GetWalletInfoCmd{},
   554  		},
   555  		{
   556  			name: "importprivkey",
   557  			newCmd: func() (interface{}, error) {
   558  				return btcjson.NewCmd("importprivkey", "abc")
   559  			},
   560  			staticCmd: func() interface{} {
   561  				return btcjson.NewImportPrivKeyCmd("abc", nil, nil)
   562  			},
   563  			marshalled: `{"jsonrpc":"1.0","method":"importprivkey","params":["abc"],"id":1}`,
   564  			unmarshalled: &btcjson.ImportPrivKeyCmd{
   565  				PrivKey: "abc",
   566  				Label:   nil,
   567  				Rescan:  btcjson.Bool(true),
   568  			},
   569  		},
   570  		{
   571  			name: "importprivkey optional1",
   572  			newCmd: func() (interface{}, error) {
   573  				return btcjson.NewCmd("importprivkey", "abc", "label")
   574  			},
   575  			staticCmd: func() interface{} {
   576  				return btcjson.NewImportPrivKeyCmd("abc", btcjson.String("label"), nil)
   577  			},
   578  			marshalled: `{"jsonrpc":"1.0","method":"importprivkey","params":["abc","label"],"id":1}`,
   579  			unmarshalled: &btcjson.ImportPrivKeyCmd{
   580  				PrivKey: "abc",
   581  				Label:   btcjson.String("label"),
   582  				Rescan:  btcjson.Bool(true),
   583  			},
   584  		},
   585  		{
   586  			name: "importprivkey optional2",
   587  			newCmd: func() (interface{}, error) {
   588  				return btcjson.NewCmd("importprivkey", "abc", "label", false)
   589  			},
   590  			staticCmd: func() interface{} {
   591  				return btcjson.NewImportPrivKeyCmd("abc", btcjson.String("label"), btcjson.Bool(false))
   592  			},
   593  			marshalled: `{"jsonrpc":"1.0","method":"importprivkey","params":["abc","label",false],"id":1}`,
   594  			unmarshalled: &btcjson.ImportPrivKeyCmd{
   595  				PrivKey: "abc",
   596  				Label:   btcjson.String("label"),
   597  				Rescan:  btcjson.Bool(false),
   598  			},
   599  		},
   600  		{
   601  			name: "keypoolrefill",
   602  			newCmd: func() (interface{}, error) {
   603  				return btcjson.NewCmd("keypoolrefill")
   604  			},
   605  			staticCmd: func() interface{} {
   606  				return btcjson.NewKeyPoolRefillCmd(nil)
   607  			},
   608  			marshalled: `{"jsonrpc":"1.0","method":"keypoolrefill","params":[],"id":1}`,
   609  			unmarshalled: &btcjson.KeyPoolRefillCmd{
   610  				NewSize: btcjson.Uint(100),
   611  			},
   612  		},
   613  		{
   614  			name: "keypoolrefill optional",
   615  			newCmd: func() (interface{}, error) {
   616  				return btcjson.NewCmd("keypoolrefill", 200)
   617  			},
   618  			staticCmd: func() interface{} {
   619  				return btcjson.NewKeyPoolRefillCmd(btcjson.Uint(200))
   620  			},
   621  			marshalled: `{"jsonrpc":"1.0","method":"keypoolrefill","params":[200],"id":1}`,
   622  			unmarshalled: &btcjson.KeyPoolRefillCmd{
   623  				NewSize: btcjson.Uint(200),
   624  			},
   625  		},
   626  		{
   627  			name: "listaccounts",
   628  			newCmd: func() (interface{}, error) {
   629  				return btcjson.NewCmd("listaccounts")
   630  			},
   631  			staticCmd: func() interface{} {
   632  				return btcjson.NewListAccountsCmd(nil)
   633  			},
   634  			marshalled: `{"jsonrpc":"1.0","method":"listaccounts","params":[],"id":1}`,
   635  			unmarshalled: &btcjson.ListAccountsCmd{
   636  				MinConf: btcjson.Int(1),
   637  			},
   638  		},
   639  		{
   640  			name: "listaccounts optional",
   641  			newCmd: func() (interface{}, error) {
   642  				return btcjson.NewCmd("listaccounts", 6)
   643  			},
   644  			staticCmd: func() interface{} {
   645  				return btcjson.NewListAccountsCmd(btcjson.Int(6))
   646  			},
   647  			marshalled: `{"jsonrpc":"1.0","method":"listaccounts","params":[6],"id":1}`,
   648  			unmarshalled: &btcjson.ListAccountsCmd{
   649  				MinConf: btcjson.Int(6),
   650  			},
   651  		},
   652  		{
   653  			name: "listaddressgroupings",
   654  			newCmd: func() (interface{}, error) {
   655  				return btcjson.NewCmd("listaddressgroupings")
   656  			},
   657  			staticCmd: func() interface{} {
   658  				return btcjson.NewListAddressGroupingsCmd()
   659  			},
   660  			marshalled:   `{"jsonrpc":"1.0","method":"listaddressgroupings","params":[],"id":1}`,
   661  			unmarshalled: &btcjson.ListAddressGroupingsCmd{},
   662  		},
   663  		{
   664  			name: "listlockunspent",
   665  			newCmd: func() (interface{}, error) {
   666  				return btcjson.NewCmd("listlockunspent")
   667  			},
   668  			staticCmd: func() interface{} {
   669  				return btcjson.NewListLockUnspentCmd()
   670  			},
   671  			marshalled:   `{"jsonrpc":"1.0","method":"listlockunspent","params":[],"id":1}`,
   672  			unmarshalled: &btcjson.ListLockUnspentCmd{},
   673  		},
   674  		{
   675  			name: "listreceivedbyaccount",
   676  			newCmd: func() (interface{}, error) {
   677  				return btcjson.NewCmd("listreceivedbyaccount")
   678  			},
   679  			staticCmd: func() interface{} {
   680  				return btcjson.NewListReceivedByAccountCmd(nil, nil, nil)
   681  			},
   682  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[],"id":1}`,
   683  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   684  				MinConf:          btcjson.Int(1),
   685  				IncludeEmpty:     btcjson.Bool(false),
   686  				IncludeWatchOnly: btcjson.Bool(false),
   687  			},
   688  		},
   689  		{
   690  			name: "listreceivedbyaccount optional1",
   691  			newCmd: func() (interface{}, error) {
   692  				return btcjson.NewCmd("listreceivedbyaccount", 6)
   693  			},
   694  			staticCmd: func() interface{} {
   695  				return btcjson.NewListReceivedByAccountCmd(btcjson.Int(6), nil, nil)
   696  			},
   697  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[6],"id":1}`,
   698  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   699  				MinConf:          btcjson.Int(6),
   700  				IncludeEmpty:     btcjson.Bool(false),
   701  				IncludeWatchOnly: btcjson.Bool(false),
   702  			},
   703  		},
   704  		{
   705  			name: "listreceivedbyaccount optional2",
   706  			newCmd: func() (interface{}, error) {
   707  				return btcjson.NewCmd("listreceivedbyaccount", 6, true)
   708  			},
   709  			staticCmd: func() interface{} {
   710  				return btcjson.NewListReceivedByAccountCmd(btcjson.Int(6), btcjson.Bool(true), nil)
   711  			},
   712  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[6,true],"id":1}`,
   713  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   714  				MinConf:          btcjson.Int(6),
   715  				IncludeEmpty:     btcjson.Bool(true),
   716  				IncludeWatchOnly: btcjson.Bool(false),
   717  			},
   718  		},
   719  		{
   720  			name: "listreceivedbyaccount optional3",
   721  			newCmd: func() (interface{}, error) {
   722  				return btcjson.NewCmd("listreceivedbyaccount", 6, true, false)
   723  			},
   724  			staticCmd: func() interface{} {
   725  				return btcjson.NewListReceivedByAccountCmd(btcjson.Int(6), btcjson.Bool(true), btcjson.Bool(false))
   726  			},
   727  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[6,true,false],"id":1}`,
   728  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   729  				MinConf:          btcjson.Int(6),
   730  				IncludeEmpty:     btcjson.Bool(true),
   731  				IncludeWatchOnly: btcjson.Bool(false),
   732  			},
   733  		},
   734  		{
   735  			name: "listreceivedbyaddress",
   736  			newCmd: func() (interface{}, error) {
   737  				return btcjson.NewCmd("listreceivedbyaddress")
   738  			},
   739  			staticCmd: func() interface{} {
   740  				return btcjson.NewListReceivedByAddressCmd(nil, nil, nil)
   741  			},
   742  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[],"id":1}`,
   743  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   744  				MinConf:          btcjson.Int(1),
   745  				IncludeEmpty:     btcjson.Bool(false),
   746  				IncludeWatchOnly: btcjson.Bool(false),
   747  			},
   748  		},
   749  		{
   750  			name: "listreceivedbyaddress optional1",
   751  			newCmd: func() (interface{}, error) {
   752  				return btcjson.NewCmd("listreceivedbyaddress", 6)
   753  			},
   754  			staticCmd: func() interface{} {
   755  				return btcjson.NewListReceivedByAddressCmd(btcjson.Int(6), nil, nil)
   756  			},
   757  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[6],"id":1}`,
   758  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   759  				MinConf:          btcjson.Int(6),
   760  				IncludeEmpty:     btcjson.Bool(false),
   761  				IncludeWatchOnly: btcjson.Bool(false),
   762  			},
   763  		},
   764  		{
   765  			name: "listreceivedbyaddress optional2",
   766  			newCmd: func() (interface{}, error) {
   767  				return btcjson.NewCmd("listreceivedbyaddress", 6, true)
   768  			},
   769  			staticCmd: func() interface{} {
   770  				return btcjson.NewListReceivedByAddressCmd(btcjson.Int(6), btcjson.Bool(true), nil)
   771  			},
   772  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[6,true],"id":1}`,
   773  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   774  				MinConf:          btcjson.Int(6),
   775  				IncludeEmpty:     btcjson.Bool(true),
   776  				IncludeWatchOnly: btcjson.Bool(false),
   777  			},
   778  		},
   779  		{
   780  			name: "listreceivedbyaddress optional3",
   781  			newCmd: func() (interface{}, error) {
   782  				return btcjson.NewCmd("listreceivedbyaddress", 6, true, false)
   783  			},
   784  			staticCmd: func() interface{} {
   785  				return btcjson.NewListReceivedByAddressCmd(btcjson.Int(6), btcjson.Bool(true), btcjson.Bool(false))
   786  			},
   787  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[6,true,false],"id":1}`,
   788  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   789  				MinConf:          btcjson.Int(6),
   790  				IncludeEmpty:     btcjson.Bool(true),
   791  				IncludeWatchOnly: btcjson.Bool(false),
   792  			},
   793  		},
   794  		{
   795  			name: "listsinceblock",
   796  			newCmd: func() (interface{}, error) {
   797  				return btcjson.NewCmd("listsinceblock")
   798  			},
   799  			staticCmd: func() interface{} {
   800  				return btcjson.NewListSinceBlockCmd(nil, nil, nil)
   801  			},
   802  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":[],"id":1}`,
   803  			unmarshalled: &btcjson.ListSinceBlockCmd{
   804  				BlockHash:           nil,
   805  				TargetConfirmations: btcjson.Int(1),
   806  				IncludeWatchOnly:    btcjson.Bool(false),
   807  			},
   808  		},
   809  		{
   810  			name: "listsinceblock optional1",
   811  			newCmd: func() (interface{}, error) {
   812  				return btcjson.NewCmd("listsinceblock", "123")
   813  			},
   814  			staticCmd: func() interface{} {
   815  				return btcjson.NewListSinceBlockCmd(btcjson.String("123"), nil, nil)
   816  			},
   817  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":["123"],"id":1}`,
   818  			unmarshalled: &btcjson.ListSinceBlockCmd{
   819  				BlockHash:           btcjson.String("123"),
   820  				TargetConfirmations: btcjson.Int(1),
   821  				IncludeWatchOnly:    btcjson.Bool(false),
   822  			},
   823  		},
   824  		{
   825  			name: "listsinceblock optional2",
   826  			newCmd: func() (interface{}, error) {
   827  				return btcjson.NewCmd("listsinceblock", "123", 6)
   828  			},
   829  			staticCmd: func() interface{} {
   830  				return btcjson.NewListSinceBlockCmd(btcjson.String("123"), btcjson.Int(6), nil)
   831  			},
   832  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":["123",6],"id":1}`,
   833  			unmarshalled: &btcjson.ListSinceBlockCmd{
   834  				BlockHash:           btcjson.String("123"),
   835  				TargetConfirmations: btcjson.Int(6),
   836  				IncludeWatchOnly:    btcjson.Bool(false),
   837  			},
   838  		},
   839  		{
   840  			name: "listsinceblock optional3",
   841  			newCmd: func() (interface{}, error) {
   842  				return btcjson.NewCmd("listsinceblock", "123", 6, true)
   843  			},
   844  			staticCmd: func() interface{} {
   845  				return btcjson.NewListSinceBlockCmd(btcjson.String("123"), btcjson.Int(6), btcjson.Bool(true))
   846  			},
   847  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":["123",6,true],"id":1}`,
   848  			unmarshalled: &btcjson.ListSinceBlockCmd{
   849  				BlockHash:           btcjson.String("123"),
   850  				TargetConfirmations: btcjson.Int(6),
   851  				IncludeWatchOnly:    btcjson.Bool(true),
   852  			},
   853  		},
   854  		{
   855  			name: "listsinceblock pad null",
   856  			newCmd: func() (interface{}, error) {
   857  				return btcjson.NewCmd("listsinceblock", "null", 1, false)
   858  			},
   859  			staticCmd: func() interface{} {
   860  				return btcjson.NewListSinceBlockCmd(nil, btcjson.Int(1), btcjson.Bool(false))
   861  			},
   862  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":[null,1,false],"id":1}`,
   863  			unmarshalled: &btcjson.ListSinceBlockCmd{
   864  				BlockHash:           nil,
   865  				TargetConfirmations: btcjson.Int(1),
   866  				IncludeWatchOnly:    btcjson.Bool(false),
   867  			},
   868  		},
   869  		{
   870  			name: "listtransactions",
   871  			newCmd: func() (interface{}, error) {
   872  				return btcjson.NewCmd("listtransactions")
   873  			},
   874  			staticCmd: func() interface{} {
   875  				return btcjson.NewListTransactionsCmd(nil, nil, nil, nil)
   876  			},
   877  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":[],"id":1}`,
   878  			unmarshalled: &btcjson.ListTransactionsCmd{
   879  				Account:          nil,
   880  				Count:            btcjson.Int(10),
   881  				From:             btcjson.Int(0),
   882  				IncludeWatchOnly: btcjson.Bool(false),
   883  			},
   884  		},
   885  		{
   886  			name: "listtransactions optional1",
   887  			newCmd: func() (interface{}, error) {
   888  				return btcjson.NewCmd("listtransactions", "acct")
   889  			},
   890  			staticCmd: func() interface{} {
   891  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), nil, nil, nil)
   892  			},
   893  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct"],"id":1}`,
   894  			unmarshalled: &btcjson.ListTransactionsCmd{
   895  				Account:          btcjson.String("acct"),
   896  				Count:            btcjson.Int(10),
   897  				From:             btcjson.Int(0),
   898  				IncludeWatchOnly: btcjson.Bool(false),
   899  			},
   900  		},
   901  		{
   902  			name: "listtransactions optional2",
   903  			newCmd: func() (interface{}, error) {
   904  				return btcjson.NewCmd("listtransactions", "acct", 20)
   905  			},
   906  			staticCmd: func() interface{} {
   907  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), btcjson.Int(20), nil, nil)
   908  			},
   909  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct",20],"id":1}`,
   910  			unmarshalled: &btcjson.ListTransactionsCmd{
   911  				Account:          btcjson.String("acct"),
   912  				Count:            btcjson.Int(20),
   913  				From:             btcjson.Int(0),
   914  				IncludeWatchOnly: btcjson.Bool(false),
   915  			},
   916  		},
   917  		{
   918  			name: "listtransactions optional3",
   919  			newCmd: func() (interface{}, error) {
   920  				return btcjson.NewCmd("listtransactions", "acct", 20, 1)
   921  			},
   922  			staticCmd: func() interface{} {
   923  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), btcjson.Int(20),
   924  					btcjson.Int(1), nil)
   925  			},
   926  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct",20,1],"id":1}`,
   927  			unmarshalled: &btcjson.ListTransactionsCmd{
   928  				Account:          btcjson.String("acct"),
   929  				Count:            btcjson.Int(20),
   930  				From:             btcjson.Int(1),
   931  				IncludeWatchOnly: btcjson.Bool(false),
   932  			},
   933  		},
   934  		{
   935  			name: "listtransactions optional4",
   936  			newCmd: func() (interface{}, error) {
   937  				return btcjson.NewCmd("listtransactions", "acct", 20, 1, true)
   938  			},
   939  			staticCmd: func() interface{} {
   940  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), btcjson.Int(20),
   941  					btcjson.Int(1), btcjson.Bool(true))
   942  			},
   943  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct",20,1,true],"id":1}`,
   944  			unmarshalled: &btcjson.ListTransactionsCmd{
   945  				Account:          btcjson.String("acct"),
   946  				Count:            btcjson.Int(20),
   947  				From:             btcjson.Int(1),
   948  				IncludeWatchOnly: btcjson.Bool(true),
   949  			},
   950  		},
   951  		{
   952  			name: "listunspent",
   953  			newCmd: func() (interface{}, error) {
   954  				return btcjson.NewCmd("listunspent")
   955  			},
   956  			staticCmd: func() interface{} {
   957  				return btcjson.NewListUnspentCmd(nil, nil, nil)
   958  			},
   959  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[],"id":1}`,
   960  			unmarshalled: &btcjson.ListUnspentCmd{
   961  				MinConf:   btcjson.Int(1),
   962  				MaxConf:   btcjson.Int(9999999),
   963  				Addresses: nil,
   964  			},
   965  		},
   966  		{
   967  			name: "listunspent optional1",
   968  			newCmd: func() (interface{}, error) {
   969  				return btcjson.NewCmd("listunspent", 6)
   970  			},
   971  			staticCmd: func() interface{} {
   972  				return btcjson.NewListUnspentCmd(btcjson.Int(6), nil, nil)
   973  			},
   974  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[6],"id":1}`,
   975  			unmarshalled: &btcjson.ListUnspentCmd{
   976  				MinConf:   btcjson.Int(6),
   977  				MaxConf:   btcjson.Int(9999999),
   978  				Addresses: nil,
   979  			},
   980  		},
   981  		{
   982  			name: "listunspent optional2",
   983  			newCmd: func() (interface{}, error) {
   984  				return btcjson.NewCmd("listunspent", 6, 100)
   985  			},
   986  			staticCmd: func() interface{} {
   987  				return btcjson.NewListUnspentCmd(btcjson.Int(6), btcjson.Int(100), nil)
   988  			},
   989  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[6,100],"id":1}`,
   990  			unmarshalled: &btcjson.ListUnspentCmd{
   991  				MinConf:   btcjson.Int(6),
   992  				MaxConf:   btcjson.Int(100),
   993  				Addresses: nil,
   994  			},
   995  		},
   996  		{
   997  			name: "listunspent optional3",
   998  			newCmd: func() (interface{}, error) {
   999  				return btcjson.NewCmd("listunspent", 6, 100, []string{"1Address", "1Address2"})
  1000  			},
  1001  			staticCmd: func() interface{} {
  1002  				return btcjson.NewListUnspentCmd(btcjson.Int(6), btcjson.Int(100),
  1003  					&[]string{"1Address", "1Address2"})
  1004  			},
  1005  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[6,100,["1Address","1Address2"]],"id":1}`,
  1006  			unmarshalled: &btcjson.ListUnspentCmd{
  1007  				MinConf:   btcjson.Int(6),
  1008  				MaxConf:   btcjson.Int(100),
  1009  				Addresses: &[]string{"1Address", "1Address2"},
  1010  			},
  1011  		},
  1012  		{
  1013  			name: "lockunspent",
  1014  			newCmd: func() (interface{}, error) {
  1015  				return btcjson.NewCmd("lockunspent", true, `[{"txid":"123","vout":1}]`)
  1016  			},
  1017  			staticCmd: func() interface{} {
  1018  				txInputs := []btcjson.TransactionInput{
  1019  					{Txid: "123", Vout: 1},
  1020  				}
  1021  				return btcjson.NewLockUnspentCmd(true, txInputs)
  1022  			},
  1023  			marshalled: `{"jsonrpc":"1.0","method":"lockunspent","params":[true,[{"txid":"123","vout":1}]],"id":1}`,
  1024  			unmarshalled: &btcjson.LockUnspentCmd{
  1025  				Unlock: true,
  1026  				Transactions: []btcjson.TransactionInput{
  1027  					{Txid: "123", Vout: 1},
  1028  				},
  1029  			},
  1030  		},
  1031  		{
  1032  			name: "move",
  1033  			newCmd: func() (interface{}, error) {
  1034  				return btcjson.NewCmd("move", "from", "to", 0.5)
  1035  			},
  1036  			staticCmd: func() interface{} {
  1037  				return btcjson.NewMoveCmd("from", "to", 0.5, nil, nil)
  1038  			},
  1039  			marshalled: `{"jsonrpc":"1.0","method":"move","params":["from","to",0.5],"id":1}`,
  1040  			unmarshalled: &btcjson.MoveCmd{
  1041  				FromAccount: "from",
  1042  				ToAccount:   "to",
  1043  				Amount:      0.5,
  1044  				MinConf:     btcjson.Int(1),
  1045  				Comment:     nil,
  1046  			},
  1047  		},
  1048  		{
  1049  			name: "move optional1",
  1050  			newCmd: func() (interface{}, error) {
  1051  				return btcjson.NewCmd("move", "from", "to", 0.5, 6)
  1052  			},
  1053  			staticCmd: func() interface{} {
  1054  				return btcjson.NewMoveCmd("from", "to", 0.5, btcjson.Int(6), nil)
  1055  			},
  1056  			marshalled: `{"jsonrpc":"1.0","method":"move","params":["from","to",0.5,6],"id":1}`,
  1057  			unmarshalled: &btcjson.MoveCmd{
  1058  				FromAccount: "from",
  1059  				ToAccount:   "to",
  1060  				Amount:      0.5,
  1061  				MinConf:     btcjson.Int(6),
  1062  				Comment:     nil,
  1063  			},
  1064  		},
  1065  		{
  1066  			name: "move optional2",
  1067  			newCmd: func() (interface{}, error) {
  1068  				return btcjson.NewCmd("move", "from", "to", 0.5, 6, "comment")
  1069  			},
  1070  			staticCmd: func() interface{} {
  1071  				return btcjson.NewMoveCmd("from", "to", 0.5, btcjson.Int(6), btcjson.String("comment"))
  1072  			},
  1073  			marshalled: `{"jsonrpc":"1.0","method":"move","params":["from","to",0.5,6,"comment"],"id":1}`,
  1074  			unmarshalled: &btcjson.MoveCmd{
  1075  				FromAccount: "from",
  1076  				ToAccount:   "to",
  1077  				Amount:      0.5,
  1078  				MinConf:     btcjson.Int(6),
  1079  				Comment:     btcjson.String("comment"),
  1080  			},
  1081  		},
  1082  		{
  1083  			name: "sendfrom",
  1084  			newCmd: func() (interface{}, error) {
  1085  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5)
  1086  			},
  1087  			staticCmd: func() interface{} {
  1088  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, nil, nil, nil)
  1089  			},
  1090  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5],"id":1}`,
  1091  			unmarshalled: &btcjson.SendFromCmd{
  1092  				FromAccount: "from",
  1093  				ToAddress:   "1Address",
  1094  				Amount:      0.5,
  1095  				MinConf:     btcjson.Int(1),
  1096  				Comment:     nil,
  1097  				CommentTo:   nil,
  1098  			},
  1099  		},
  1100  		{
  1101  			name: "sendfrom optional1",
  1102  			newCmd: func() (interface{}, error) {
  1103  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5, 6)
  1104  			},
  1105  			staticCmd: func() interface{} {
  1106  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, btcjson.Int(6), nil, nil)
  1107  			},
  1108  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5,6],"id":1}`,
  1109  			unmarshalled: &btcjson.SendFromCmd{
  1110  				FromAccount: "from",
  1111  				ToAddress:   "1Address",
  1112  				Amount:      0.5,
  1113  				MinConf:     btcjson.Int(6),
  1114  				Comment:     nil,
  1115  				CommentTo:   nil,
  1116  			},
  1117  		},
  1118  		{
  1119  			name: "sendfrom optional2",
  1120  			newCmd: func() (interface{}, error) {
  1121  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5, 6, "comment")
  1122  			},
  1123  			staticCmd: func() interface{} {
  1124  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, btcjson.Int(6),
  1125  					btcjson.String("comment"), nil)
  1126  			},
  1127  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5,6,"comment"],"id":1}`,
  1128  			unmarshalled: &btcjson.SendFromCmd{
  1129  				FromAccount: "from",
  1130  				ToAddress:   "1Address",
  1131  				Amount:      0.5,
  1132  				MinConf:     btcjson.Int(6),
  1133  				Comment:     btcjson.String("comment"),
  1134  				CommentTo:   nil,
  1135  			},
  1136  		},
  1137  		{
  1138  			name: "sendfrom optional3",
  1139  			newCmd: func() (interface{}, error) {
  1140  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5, 6, "comment", "commentto")
  1141  			},
  1142  			staticCmd: func() interface{} {
  1143  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, btcjson.Int(6),
  1144  					btcjson.String("comment"), btcjson.String("commentto"))
  1145  			},
  1146  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5,6,"comment","commentto"],"id":1}`,
  1147  			unmarshalled: &btcjson.SendFromCmd{
  1148  				FromAccount: "from",
  1149  				ToAddress:   "1Address",
  1150  				Amount:      0.5,
  1151  				MinConf:     btcjson.Int(6),
  1152  				Comment:     btcjson.String("comment"),
  1153  				CommentTo:   btcjson.String("commentto"),
  1154  			},
  1155  		},
  1156  		{
  1157  			name: "sendmany",
  1158  			newCmd: func() (interface{}, error) {
  1159  				return btcjson.NewCmd("sendmany", "from", `{"1Address":0.5}`)
  1160  			},
  1161  			staticCmd: func() interface{} {
  1162  				amounts := map[string]float64{"1Address": 0.5}
  1163  				return btcjson.NewSendManyCmd("from", amounts, nil, nil)
  1164  			},
  1165  			marshalled: `{"jsonrpc":"1.0","method":"sendmany","params":["from",{"1Address":0.5}],"id":1}`,
  1166  			unmarshalled: &btcjson.SendManyCmd{
  1167  				FromAccount: "from",
  1168  				Amounts:     map[string]float64{"1Address": 0.5},
  1169  				MinConf:     btcjson.Int(1),
  1170  				Comment:     nil,
  1171  			},
  1172  		},
  1173  		{
  1174  			name: "sendmany optional1",
  1175  			newCmd: func() (interface{}, error) {
  1176  				return btcjson.NewCmd("sendmany", "from", `{"1Address":0.5}`, 6)
  1177  			},
  1178  			staticCmd: func() interface{} {
  1179  				amounts := map[string]float64{"1Address": 0.5}
  1180  				return btcjson.NewSendManyCmd("from", amounts, btcjson.Int(6), nil)
  1181  			},
  1182  			marshalled: `{"jsonrpc":"1.0","method":"sendmany","params":["from",{"1Address":0.5},6],"id":1}`,
  1183  			unmarshalled: &btcjson.SendManyCmd{
  1184  				FromAccount: "from",
  1185  				Amounts:     map[string]float64{"1Address": 0.5},
  1186  				MinConf:     btcjson.Int(6),
  1187  				Comment:     nil,
  1188  			},
  1189  		},
  1190  		{
  1191  			name: "sendmany optional2",
  1192  			newCmd: func() (interface{}, error) {
  1193  				return btcjson.NewCmd("sendmany", "from", `{"1Address":0.5}`, 6, "comment")
  1194  			},
  1195  			staticCmd: func() interface{} {
  1196  				amounts := map[string]float64{"1Address": 0.5}
  1197  				return btcjson.NewSendManyCmd("from", amounts, btcjson.Int(6), btcjson.String("comment"))
  1198  			},
  1199  			marshalled: `{"jsonrpc":"1.0","method":"sendmany","params":["from",{"1Address":0.5},6,"comment"],"id":1}`,
  1200  			unmarshalled: &btcjson.SendManyCmd{
  1201  				FromAccount: "from",
  1202  				Amounts:     map[string]float64{"1Address": 0.5},
  1203  				MinConf:     btcjson.Int(6),
  1204  				Comment:     btcjson.String("comment"),
  1205  			},
  1206  		},
  1207  		{
  1208  			name: "sendtoaddress",
  1209  			newCmd: func() (interface{}, error) {
  1210  				return btcjson.NewCmd("sendtoaddress", "1Address", 0.5)
  1211  			},
  1212  			staticCmd: func() interface{} {
  1213  				return btcjson.NewSendToAddressCmd("1Address", 0.5, nil, nil)
  1214  			},
  1215  			marshalled: `{"jsonrpc":"1.0","method":"sendtoaddress","params":["1Address",0.5],"id":1}`,
  1216  			unmarshalled: &btcjson.SendToAddressCmd{
  1217  				Address:   "1Address",
  1218  				Amount:    0.5,
  1219  				Comment:   nil,
  1220  				CommentTo: nil,
  1221  			},
  1222  		},
  1223  		{
  1224  			name: "sendtoaddress optional1",
  1225  			newCmd: func() (interface{}, error) {
  1226  				return btcjson.NewCmd("sendtoaddress", "1Address", 0.5, "comment", "commentto")
  1227  			},
  1228  			staticCmd: func() interface{} {
  1229  				return btcjson.NewSendToAddressCmd("1Address", 0.5, btcjson.String("comment"),
  1230  					btcjson.String("commentto"))
  1231  			},
  1232  			marshalled: `{"jsonrpc":"1.0","method":"sendtoaddress","params":["1Address",0.5,"comment","commentto"],"id":1}`,
  1233  			unmarshalled: &btcjson.SendToAddressCmd{
  1234  				Address:   "1Address",
  1235  				Amount:    0.5,
  1236  				Comment:   btcjson.String("comment"),
  1237  				CommentTo: btcjson.String("commentto"),
  1238  			},
  1239  		},
  1240  		{
  1241  			name: "setaccount",
  1242  			newCmd: func() (interface{}, error) {
  1243  				return btcjson.NewCmd("setaccount", "1Address", "acct")
  1244  			},
  1245  			staticCmd: func() interface{} {
  1246  				return btcjson.NewSetAccountCmd("1Address", "acct")
  1247  			},
  1248  			marshalled: `{"jsonrpc":"1.0","method":"setaccount","params":["1Address","acct"],"id":1}`,
  1249  			unmarshalled: &btcjson.SetAccountCmd{
  1250  				Address: "1Address",
  1251  				Account: "acct",
  1252  			},
  1253  		},
  1254  		{
  1255  			name: "settxfee",
  1256  			newCmd: func() (interface{}, error) {
  1257  				return btcjson.NewCmd("settxfee", 0.0001)
  1258  			},
  1259  			staticCmd: func() interface{} {
  1260  				return btcjson.NewSetTxFeeCmd(0.0001)
  1261  			},
  1262  			marshalled: `{"jsonrpc":"1.0","method":"settxfee","params":[0.0001],"id":1}`,
  1263  			unmarshalled: &btcjson.SetTxFeeCmd{
  1264  				Amount: 0.0001,
  1265  			},
  1266  		},
  1267  		{
  1268  			name: "signmessage",
  1269  			newCmd: func() (interface{}, error) {
  1270  				return btcjson.NewCmd("signmessage", "1Address", "message")
  1271  			},
  1272  			staticCmd: func() interface{} {
  1273  				return btcjson.NewSignMessageCmd("1Address", "message")
  1274  			},
  1275  			marshalled: `{"jsonrpc":"1.0","method":"signmessage","params":["1Address","message"],"id":1}`,
  1276  			unmarshalled: &btcjson.SignMessageCmd{
  1277  				Address: "1Address",
  1278  				Message: "message",
  1279  			},
  1280  		},
  1281  		{
  1282  			name: "signrawtransaction",
  1283  			newCmd: func() (interface{}, error) {
  1284  				return btcjson.NewCmd("signrawtransaction", "001122")
  1285  			},
  1286  			staticCmd: func() interface{} {
  1287  				return btcjson.NewSignRawTransactionCmd("001122", nil, nil, nil)
  1288  			},
  1289  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122"],"id":1}`,
  1290  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1291  				RawTx:    "001122",
  1292  				Inputs:   nil,
  1293  				PrivKeys: nil,
  1294  				Flags:    btcjson.String("ALL"),
  1295  			},
  1296  		},
  1297  		{
  1298  			name: "signrawtransaction optional1",
  1299  			newCmd: func() (interface{}, error) {
  1300  				return btcjson.NewCmd("signrawtransaction", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]`)
  1301  			},
  1302  			staticCmd: func() interface{} {
  1303  				txInputs := []btcjson.RawTxInput{
  1304  					{
  1305  						Txid:         "123",
  1306  						Vout:         1,
  1307  						ScriptPubKey: "00",
  1308  						RedeemScript: "01",
  1309  					},
  1310  				}
  1311  
  1312  				return btcjson.NewSignRawTransactionCmd("001122", &txInputs, nil, nil)
  1313  			},
  1314  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]],"id":1}`,
  1315  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1316  				RawTx: "001122",
  1317  				Inputs: &[]btcjson.RawTxInput{
  1318  					{
  1319  						Txid:         "123",
  1320  						Vout:         1,
  1321  						ScriptPubKey: "00",
  1322  						RedeemScript: "01",
  1323  					},
  1324  				},
  1325  				PrivKeys: nil,
  1326  				Flags:    btcjson.String("ALL"),
  1327  			},
  1328  		},
  1329  		{
  1330  			name: "signrawtransaction optional2",
  1331  			newCmd: func() (interface{}, error) {
  1332  				return btcjson.NewCmd("signrawtransaction", "001122", `[]`, `["abc"]`)
  1333  			},
  1334  			staticCmd: func() interface{} {
  1335  				txInputs := []btcjson.RawTxInput{}
  1336  				privKeys := []string{"abc"}
  1337  				return btcjson.NewSignRawTransactionCmd("001122", &txInputs, &privKeys, nil)
  1338  			},
  1339  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122",[],["abc"]],"id":1}`,
  1340  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1341  				RawTx:    "001122",
  1342  				Inputs:   &[]btcjson.RawTxInput{},
  1343  				PrivKeys: &[]string{"abc"},
  1344  				Flags:    btcjson.String("ALL"),
  1345  			},
  1346  		},
  1347  		{
  1348  			name: "signrawtransaction optional3",
  1349  			newCmd: func() (interface{}, error) {
  1350  				return btcjson.NewCmd("signrawtransaction", "001122", `[]`, `[]`, "ALL")
  1351  			},
  1352  			staticCmd: func() interface{} {
  1353  				txInputs := []btcjson.RawTxInput{}
  1354  				privKeys := []string{}
  1355  				return btcjson.NewSignRawTransactionCmd("001122", &txInputs, &privKeys,
  1356  					btcjson.String("ALL"))
  1357  			},
  1358  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122",[],[],"ALL"],"id":1}`,
  1359  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1360  				RawTx:    "001122",
  1361  				Inputs:   &[]btcjson.RawTxInput{},
  1362  				PrivKeys: &[]string{},
  1363  				Flags:    btcjson.String("ALL"),
  1364  			},
  1365  		},
  1366  		{
  1367  			name: "signrawtransactionwithwallet",
  1368  			newCmd: func() (interface{}, error) {
  1369  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122")
  1370  			},
  1371  			staticCmd: func() interface{} {
  1372  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", nil, nil)
  1373  			},
  1374  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122"],"id":1}`,
  1375  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1376  				RawTx:       "001122",
  1377  				Inputs:      nil,
  1378  				SigHashType: btcjson.String("ALL"),
  1379  			},
  1380  		},
  1381  		{
  1382  			name: "signrawtransactionwithwallet optional1",
  1383  			newCmd: func() (interface{}, error) {
  1384  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01","witnessScript":"02","amount":1.5}]`)
  1385  			},
  1386  			staticCmd: func() interface{} {
  1387  				txInputs := []btcjson.RawTxWitnessInput{
  1388  					{
  1389  						Txid:          "123",
  1390  						Vout:          1,
  1391  						ScriptPubKey:  "00",
  1392  						RedeemScript:  btcjson.String("01"),
  1393  						WitnessScript: btcjson.String("02"),
  1394  						Amount:        btcjson.Float64(1.5),
  1395  					},
  1396  				}
  1397  
  1398  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, nil)
  1399  			},
  1400  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01","witnessScript":"02","amount":1.5}]],"id":1}`,
  1401  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1402  				RawTx: "001122",
  1403  				Inputs: &[]btcjson.RawTxWitnessInput{
  1404  					{
  1405  						Txid:          "123",
  1406  						Vout:          1,
  1407  						ScriptPubKey:  "00",
  1408  						RedeemScript:  btcjson.String("01"),
  1409  						WitnessScript: btcjson.String("02"),
  1410  						Amount:        btcjson.Float64(1.5),
  1411  					},
  1412  				},
  1413  				SigHashType: btcjson.String("ALL"),
  1414  			},
  1415  		},
  1416  		{
  1417  			name: "signrawtransactionwithwallet optional1 with blank fields in input",
  1418  			newCmd: func() (interface{}, error) {
  1419  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]`)
  1420  			},
  1421  			staticCmd: func() interface{} {
  1422  				txInputs := []btcjson.RawTxWitnessInput{
  1423  					{
  1424  						Txid:         "123",
  1425  						Vout:         1,
  1426  						ScriptPubKey: "00",
  1427  						RedeemScript: btcjson.String("01"),
  1428  					},
  1429  				}
  1430  
  1431  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, nil)
  1432  			},
  1433  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]],"id":1}`,
  1434  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1435  				RawTx: "001122",
  1436  				Inputs: &[]btcjson.RawTxWitnessInput{
  1437  					{
  1438  						Txid:         "123",
  1439  						Vout:         1,
  1440  						ScriptPubKey: "00",
  1441  						RedeemScript: btcjson.String("01"),
  1442  					},
  1443  				},
  1444  				SigHashType: btcjson.String("ALL"),
  1445  			},
  1446  		},
  1447  		{
  1448  			name: "signrawtransactionwithwallet optional2",
  1449  			newCmd: func() (interface{}, error) {
  1450  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[]`, "ALL")
  1451  			},
  1452  			staticCmd: func() interface{} {
  1453  				txInputs := []btcjson.RawTxWitnessInput{}
  1454  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, btcjson.String("ALL"))
  1455  			},
  1456  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[],"ALL"],"id":1}`,
  1457  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1458  				RawTx:       "001122",
  1459  				Inputs:      &[]btcjson.RawTxWitnessInput{},
  1460  				SigHashType: btcjson.String("ALL"),
  1461  			},
  1462  		},
  1463  		{
  1464  			name: "walletlock",
  1465  			newCmd: func() (interface{}, error) {
  1466  				return btcjson.NewCmd("walletlock")
  1467  			},
  1468  			staticCmd: func() interface{} {
  1469  				return btcjson.NewWalletLockCmd()
  1470  			},
  1471  			marshalled:   `{"jsonrpc":"1.0","method":"walletlock","params":[],"id":1}`,
  1472  			unmarshalled: &btcjson.WalletLockCmd{},
  1473  		},
  1474  		{
  1475  			name: "walletpassphrase",
  1476  			newCmd: func() (interface{}, error) {
  1477  				return btcjson.NewCmd("walletpassphrase", "pass", 60)
  1478  			},
  1479  			staticCmd: func() interface{} {
  1480  				return btcjson.NewWalletPassphraseCmd("pass", 60)
  1481  			},
  1482  			marshalled: `{"jsonrpc":"1.0","method":"walletpassphrase","params":["pass",60],"id":1}`,
  1483  			unmarshalled: &btcjson.WalletPassphraseCmd{
  1484  				Passphrase: "pass",
  1485  				Timeout:    60,
  1486  			},
  1487  		},
  1488  		{
  1489  			name: "walletpassphrasechange",
  1490  			newCmd: func() (interface{}, error) {
  1491  				return btcjson.NewCmd("walletpassphrasechange", "old", "new")
  1492  			},
  1493  			staticCmd: func() interface{} {
  1494  				return btcjson.NewWalletPassphraseChangeCmd("old", "new")
  1495  			},
  1496  			marshalled: `{"jsonrpc":"1.0","method":"walletpassphrasechange","params":["old","new"],"id":1}`,
  1497  			unmarshalled: &btcjson.WalletPassphraseChangeCmd{
  1498  				OldPassphrase: "old",
  1499  				NewPassphrase: "new",
  1500  			},
  1501  		},
  1502  		{
  1503  			name: "importmulti with descriptor + options",
  1504  			newCmd: func() (interface{}, error) {
  1505  				return btcjson.NewCmd(
  1506  					"importmulti",
  1507  					// Cannot use a native string, due to special types like timestamp.
  1508  					[]btcjson.ImportMultiRequest{
  1509  						{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: 0}},
  1510  					},
  1511  					`{"rescan": true}`,
  1512  				)
  1513  			},
  1514  			staticCmd: func() interface{} {
  1515  				requests := []btcjson.ImportMultiRequest{
  1516  					{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: 0}},
  1517  				}
  1518  				options := btcjson.ImportMultiOptions{Rescan: true}
  1519  				return btcjson.NewImportMultiCmd(requests, &options)
  1520  			},
  1521  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0}],{"rescan":true}],"id":1}`,
  1522  			unmarshalled: &btcjson.ImportMultiCmd{
  1523  				Requests: []btcjson.ImportMultiRequest{
  1524  					{
  1525  						Descriptor: btcjson.String("123"),
  1526  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1527  					},
  1528  				},
  1529  				Options: &btcjson.ImportMultiOptions{Rescan: true},
  1530  			},
  1531  		},
  1532  		{
  1533  			name: "importmulti with descriptor + no options",
  1534  			newCmd: func() (interface{}, error) {
  1535  				return btcjson.NewCmd(
  1536  					"importmulti",
  1537  					// Cannot use a native string, due to special types like timestamp.
  1538  					[]btcjson.ImportMultiRequest{
  1539  						{
  1540  							Descriptor: btcjson.String("123"),
  1541  							Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1542  							WatchOnly:  btcjson.Bool(false),
  1543  							Internal:   btcjson.Bool(true),
  1544  							Label:      btcjson.String("aaa"),
  1545  							KeyPool:    btcjson.Bool(false),
  1546  						},
  1547  					},
  1548  				)
  1549  			},
  1550  			staticCmd: func() interface{} {
  1551  				requests := []btcjson.ImportMultiRequest{
  1552  					{
  1553  						Descriptor: btcjson.String("123"),
  1554  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1555  						WatchOnly:  btcjson.Bool(false),
  1556  						Internal:   btcjson.Bool(true),
  1557  						Label:      btcjson.String("aaa"),
  1558  						KeyPool:    btcjson.Bool(false),
  1559  					},
  1560  				}
  1561  				return btcjson.NewImportMultiCmd(requests, nil)
  1562  			},
  1563  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"internal":true,"watchonly":false,"label":"aaa","keypool":false}]],"id":1}`,
  1564  			unmarshalled: &btcjson.ImportMultiCmd{
  1565  				Requests: []btcjson.ImportMultiRequest{
  1566  					{
  1567  						Descriptor: btcjson.String("123"),
  1568  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1569  						WatchOnly:  btcjson.Bool(false),
  1570  						Internal:   btcjson.Bool(true),
  1571  						Label:      btcjson.String("aaa"),
  1572  						KeyPool:    btcjson.Bool(false),
  1573  					},
  1574  				},
  1575  			},
  1576  		},
  1577  		{
  1578  			name: "importmulti with descriptor + string timestamp",
  1579  			newCmd: func() (interface{}, error) {
  1580  				return btcjson.NewCmd(
  1581  					"importmulti",
  1582  					// Cannot use a native string, due to special types like timestamp.
  1583  					[]btcjson.ImportMultiRequest{
  1584  						{
  1585  							Descriptor: btcjson.String("123"),
  1586  							Timestamp:  btcjson.TimestampOrNow{Value: "now"},
  1587  						},
  1588  					},
  1589  				)
  1590  			},
  1591  			staticCmd: func() interface{} {
  1592  				requests := []btcjson.ImportMultiRequest{
  1593  					{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: "now"}},
  1594  				}
  1595  				return btcjson.NewImportMultiCmd(requests, nil)
  1596  			},
  1597  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":"now"}]],"id":1}`,
  1598  			unmarshalled: &btcjson.ImportMultiCmd{
  1599  				Requests: []btcjson.ImportMultiRequest{
  1600  					{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: "now"}},
  1601  				},
  1602  			},
  1603  		},
  1604  		{
  1605  			name: "importmulti with scriptPubKey script",
  1606  			newCmd: func() (interface{}, error) {
  1607  				return btcjson.NewCmd(
  1608  					"importmulti",
  1609  					// Cannot use a native string, due to special types like timestamp and scriptPubKey
  1610  					[]btcjson.ImportMultiRequest{
  1611  						{
  1612  							ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"},
  1613  							RedeemScript: btcjson.String("123"),
  1614  							Timestamp:    btcjson.TimestampOrNow{Value: 0},
  1615  							PubKeys:      &[]string{"aaa"},
  1616  						},
  1617  					},
  1618  				)
  1619  			},
  1620  			staticCmd: func() interface{} {
  1621  				requests := []btcjson.ImportMultiRequest{
  1622  					{
  1623  						ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"},
  1624  						RedeemScript: btcjson.String("123"),
  1625  						Timestamp:    btcjson.TimestampOrNow{Value: 0},
  1626  						PubKeys:      &[]string{"aaa"},
  1627  					},
  1628  				}
  1629  				return btcjson.NewImportMultiCmd(requests, nil)
  1630  			},
  1631  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"scriptPubKey":"script","timestamp":0,"redeemscript":"123","pubkeys":["aaa"]}]],"id":1}`,
  1632  			unmarshalled: &btcjson.ImportMultiCmd{
  1633  				Requests: []btcjson.ImportMultiRequest{
  1634  					{
  1635  						ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"},
  1636  						RedeemScript: btcjson.String("123"),
  1637  						Timestamp:    btcjson.TimestampOrNow{Value: 0},
  1638  						PubKeys:      &[]string{"aaa"},
  1639  					},
  1640  				},
  1641  			},
  1642  		},
  1643  		{
  1644  			name: "importmulti with scriptPubKey address",
  1645  			newCmd: func() (interface{}, error) {
  1646  				return btcjson.NewCmd(
  1647  					"importmulti",
  1648  					// Cannot use a native string, due to special types like timestamp and scriptPubKey
  1649  					[]btcjson.ImportMultiRequest{
  1650  						{
  1651  							ScriptPubKey:  &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}},
  1652  							WitnessScript: btcjson.String("123"),
  1653  							Timestamp:     btcjson.TimestampOrNow{Value: 0},
  1654  							Keys:          &[]string{"aaa"},
  1655  						},
  1656  					},
  1657  				)
  1658  			},
  1659  			staticCmd: func() interface{} {
  1660  				requests := []btcjson.ImportMultiRequest{
  1661  					{
  1662  						ScriptPubKey:  &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}},
  1663  						WitnessScript: btcjson.String("123"),
  1664  						Timestamp:     btcjson.TimestampOrNow{Value: 0},
  1665  						Keys:          &[]string{"aaa"},
  1666  					},
  1667  				}
  1668  				return btcjson.NewImportMultiCmd(requests, nil)
  1669  			},
  1670  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"scriptPubKey":{"address":"addr"},"timestamp":0,"witnessscript":"123","keys":["aaa"]}]],"id":1}`,
  1671  			unmarshalled: &btcjson.ImportMultiCmd{
  1672  				Requests: []btcjson.ImportMultiRequest{
  1673  					{
  1674  						ScriptPubKey:  &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}},
  1675  						WitnessScript: btcjson.String("123"),
  1676  						Timestamp:     btcjson.TimestampOrNow{Value: 0},
  1677  						Keys:          &[]string{"aaa"},
  1678  					},
  1679  				},
  1680  			},
  1681  		},
  1682  		{
  1683  			name: "importmulti with ranged (int) descriptor",
  1684  			newCmd: func() (interface{}, error) {
  1685  				return btcjson.NewCmd(
  1686  					"importmulti",
  1687  					// Cannot use a native string, due to special types like timestamp.
  1688  					[]btcjson.ImportMultiRequest{
  1689  						{
  1690  							Descriptor: btcjson.String("123"),
  1691  							Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1692  							Range:      &btcjson.DescriptorRange{Value: 7},
  1693  						},
  1694  					},
  1695  				)
  1696  			},
  1697  			staticCmd: func() interface{} {
  1698  				requests := []btcjson.ImportMultiRequest{
  1699  					{
  1700  						Descriptor: btcjson.String("123"),
  1701  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1702  						Range:      &btcjson.DescriptorRange{Value: 7},
  1703  					},
  1704  				}
  1705  				return btcjson.NewImportMultiCmd(requests, nil)
  1706  			},
  1707  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"range":7}]],"id":1}`,
  1708  			unmarshalled: &btcjson.ImportMultiCmd{
  1709  				Requests: []btcjson.ImportMultiRequest{
  1710  					{
  1711  						Descriptor: btcjson.String("123"),
  1712  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1713  						Range:      &btcjson.DescriptorRange{Value: 7},
  1714  					},
  1715  				},
  1716  			},
  1717  		},
  1718  		{
  1719  			name: "importmulti with ranged (slice) descriptor",
  1720  			newCmd: func() (interface{}, error) {
  1721  				return btcjson.NewCmd(
  1722  					"importmulti",
  1723  					// Cannot use a native string, due to special types like timestamp.
  1724  					[]btcjson.ImportMultiRequest{
  1725  						{
  1726  							Descriptor: btcjson.String("123"),
  1727  							Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1728  							Range:      &btcjson.DescriptorRange{Value: []int{1, 7}},
  1729  						},
  1730  					},
  1731  				)
  1732  			},
  1733  			staticCmd: func() interface{} {
  1734  				requests := []btcjson.ImportMultiRequest{
  1735  					{
  1736  						Descriptor: btcjson.String("123"),
  1737  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1738  						Range:      &btcjson.DescriptorRange{Value: []int{1, 7}},
  1739  					},
  1740  				}
  1741  				return btcjson.NewImportMultiCmd(requests, nil)
  1742  			},
  1743  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"range":[1,7]}]],"id":1}`,
  1744  			unmarshalled: &btcjson.ImportMultiCmd{
  1745  				Requests: []btcjson.ImportMultiRequest{
  1746  					{
  1747  						Descriptor: btcjson.String("123"),
  1748  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1749  						Range:      &btcjson.DescriptorRange{Value: []int{1, 7}},
  1750  					},
  1751  				},
  1752  			},
  1753  		},
  1754  		{
  1755  			name: "walletcreatefundedpsbt",
  1756  			newCmd: func() (interface{}, error) {
  1757  				return btcjson.NewCmd(
  1758  					"walletcreatefundedpsbt",
  1759  					[]btcjson.PsbtInput{
  1760  						{
  1761  							Txid:     "1234",
  1762  							Vout:     0,
  1763  							Sequence: 0,
  1764  						},
  1765  					},
  1766  					[]btcjson.PsbtOutput{
  1767  						btcjson.NewPsbtOutput("1234", btcutil.Amount(1234)),
  1768  						btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}),
  1769  					},
  1770  					btcjson.Uint32(1),
  1771  					btcjson.WalletCreateFundedPsbtOpts{},
  1772  					btcjson.Bool(true),
  1773  				)
  1774  			},
  1775  			staticCmd: func() interface{} {
  1776  				return btcjson.NewWalletCreateFundedPsbtCmd(
  1777  					[]btcjson.PsbtInput{
  1778  						{
  1779  							Txid:     "1234",
  1780  							Vout:     0,
  1781  							Sequence: 0,
  1782  						},
  1783  					},
  1784  					[]btcjson.PsbtOutput{
  1785  						btcjson.NewPsbtOutput("1234", btcutil.Amount(1234)),
  1786  						btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}),
  1787  					},
  1788  					btcjson.Uint32(1),
  1789  					&btcjson.WalletCreateFundedPsbtOpts{},
  1790  					btcjson.Bool(true),
  1791  				)
  1792  			},
  1793  			marshalled: `{"jsonrpc":"1.0","method":"walletcreatefundedpsbt","params":[[{"txid":"1234","vout":0,"sequence":0}],[{"1234":0.00001234},{"data":"01020304"}],1,{},true],"id":1}`,
  1794  			unmarshalled: &btcjson.WalletCreateFundedPsbtCmd{
  1795  				Inputs: []btcjson.PsbtInput{
  1796  					{
  1797  						Txid:     "1234",
  1798  						Vout:     0,
  1799  						Sequence: 0,
  1800  					},
  1801  				},
  1802  				Outputs: []btcjson.PsbtOutput{
  1803  					btcjson.NewPsbtOutput("1234", btcutil.Amount(1234)),
  1804  					btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}),
  1805  				},
  1806  				Locktime:    btcjson.Uint32(1),
  1807  				Options:     &btcjson.WalletCreateFundedPsbtOpts{},
  1808  				Bip32Derivs: btcjson.Bool(true),
  1809  			},
  1810  		},
  1811  		{
  1812  			name: "walletprocesspsbt",
  1813  			newCmd: func() (interface{}, error) {
  1814  				return btcjson.NewCmd(
  1815  					"walletprocesspsbt", "1234", btcjson.Bool(true), btcjson.String("ALL"), btcjson.Bool(true))
  1816  			},
  1817  			staticCmd: func() interface{} {
  1818  				return btcjson.NewWalletProcessPsbtCmd(
  1819  					"1234", btcjson.Bool(true), btcjson.String("ALL"), btcjson.Bool(true))
  1820  			},
  1821  			marshalled: `{"jsonrpc":"1.0","method":"walletprocesspsbt","params":["1234",true,"ALL",true],"id":1}`,
  1822  			unmarshalled: &btcjson.WalletProcessPsbtCmd{
  1823  				Psbt:        "1234",
  1824  				Sign:        btcjson.Bool(true),
  1825  				SighashType: btcjson.String("ALL"),
  1826  				Bip32Derivs: btcjson.Bool(true),
  1827  			},
  1828  		},
  1829  	}
  1830  
  1831  	t.Logf("Running %d tests", len(tests))
  1832  	for i, test := range tests {
  1833  		// Marshal the command as created by the new static command
  1834  		// creation function.
  1835  		marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd())
  1836  		if err != nil {
  1837  			t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
  1838  				test.name, err)
  1839  			continue
  1840  		}
  1841  
  1842  		if !bytes.Equal(marshalled, []byte(test.marshalled)) {
  1843  			t.Errorf("Test #%d (%s) unexpected marshalled data - "+
  1844  				"got %s, want %s", i, test.name, marshalled,
  1845  				test.marshalled)
  1846  			continue
  1847  		}
  1848  
  1849  		// Ensure the command is created without error via the generic
  1850  		// new command creation function.
  1851  		cmd, err := test.newCmd()
  1852  		if err != nil {
  1853  			t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
  1854  				i, test.name, err)
  1855  		}
  1856  
  1857  		// Marshal the command as created by the generic new command
  1858  		// creation function.
  1859  		marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd)
  1860  		if err != nil {
  1861  			t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
  1862  				test.name, err)
  1863  			continue
  1864  		}
  1865  
  1866  		if !bytes.Equal(marshalled, []byte(test.marshalled)) {
  1867  			t.Errorf("Test #%d (%s) unexpected marshalled data - "+
  1868  				"got %s, want %s", i, test.name, marshalled,
  1869  				test.marshalled)
  1870  			continue
  1871  		}
  1872  
  1873  		var request btcjson.Request
  1874  		if err := json.Unmarshal(marshalled, &request); err != nil {
  1875  			t.Errorf("Test #%d (%s) unexpected error while "+
  1876  				"unmarshalling JSON-RPC request: %v", i,
  1877  				test.name, err)
  1878  			continue
  1879  		}
  1880  
  1881  		cmd, err = btcjson.UnmarshalCmd(&request)
  1882  		if err != nil {
  1883  			t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
  1884  				test.name, err)
  1885  			continue
  1886  		}
  1887  
  1888  		if !reflect.DeepEqual(cmd, test.unmarshalled) {
  1889  			t.Errorf("Test #%d (%s) unexpected unmarshalled command "+
  1890  				"- got %s, want %s", i, test.name,
  1891  				fmt.Sprintf("(%T) %+[1]v", cmd),
  1892  				fmt.Sprintf("(%T) %+[1]v\n", test.unmarshalled))
  1893  			continue
  1894  		}
  1895  	}
  1896  }