github.com/palcoin-project/palcd@v1.0.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/palcoin-project/palcd/btcjson"
    15  	"github.com/palcoin-project/palcutil"
    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)
   383  			},
   384  			marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":[],"id":1}`,
   385  			unmarshalled: &btcjson.GetNewAddressCmd{
   386  				Account: nil,
   387  			},
   388  		},
   389  		{
   390  			name: "getnewaddress optional",
   391  			newCmd: func() (interface{}, error) {
   392  				return btcjson.NewCmd("getnewaddress", "acct")
   393  			},
   394  			staticCmd: func() interface{} {
   395  				return btcjson.NewGetNewAddressCmd(btcjson.String("acct"))
   396  			},
   397  			marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":["acct"],"id":1}`,
   398  			unmarshalled: &btcjson.GetNewAddressCmd{
   399  				Account: btcjson.String("acct"),
   400  			},
   401  		},
   402  		{
   403  			name: "getrawchangeaddress",
   404  			newCmd: func() (interface{}, error) {
   405  				return btcjson.NewCmd("getrawchangeaddress")
   406  			},
   407  			staticCmd: func() interface{} {
   408  				return btcjson.NewGetRawChangeAddressCmd(nil)
   409  			},
   410  			marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":[],"id":1}`,
   411  			unmarshalled: &btcjson.GetRawChangeAddressCmd{
   412  				Account: nil,
   413  			},
   414  		},
   415  		{
   416  			name: "getrawchangeaddress optional",
   417  			newCmd: func() (interface{}, error) {
   418  				return btcjson.NewCmd("getrawchangeaddress", "acct")
   419  			},
   420  			staticCmd: func() interface{} {
   421  				return btcjson.NewGetRawChangeAddressCmd(btcjson.String("acct"))
   422  			},
   423  			marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":["acct"],"id":1}`,
   424  			unmarshalled: &btcjson.GetRawChangeAddressCmd{
   425  				Account: btcjson.String("acct"),
   426  			},
   427  		},
   428  		{
   429  			name: "getreceivedbyaccount",
   430  			newCmd: func() (interface{}, error) {
   431  				return btcjson.NewCmd("getreceivedbyaccount", "acct")
   432  			},
   433  			staticCmd: func() interface{} {
   434  				return btcjson.NewGetReceivedByAccountCmd("acct", nil)
   435  			},
   436  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaccount","params":["acct"],"id":1}`,
   437  			unmarshalled: &btcjson.GetReceivedByAccountCmd{
   438  				Account: "acct",
   439  				MinConf: btcjson.Int(1),
   440  			},
   441  		},
   442  		{
   443  			name: "getreceivedbyaccount optional",
   444  			newCmd: func() (interface{}, error) {
   445  				return btcjson.NewCmd("getreceivedbyaccount", "acct", 6)
   446  			},
   447  			staticCmd: func() interface{} {
   448  				return btcjson.NewGetReceivedByAccountCmd("acct", btcjson.Int(6))
   449  			},
   450  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaccount","params":["acct",6],"id":1}`,
   451  			unmarshalled: &btcjson.GetReceivedByAccountCmd{
   452  				Account: "acct",
   453  				MinConf: btcjson.Int(6),
   454  			},
   455  		},
   456  		{
   457  			name: "getreceivedbyaddress",
   458  			newCmd: func() (interface{}, error) {
   459  				return btcjson.NewCmd("getreceivedbyaddress", "1Address")
   460  			},
   461  			staticCmd: func() interface{} {
   462  				return btcjson.NewGetReceivedByAddressCmd("1Address", nil)
   463  			},
   464  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaddress","params":["1Address"],"id":1}`,
   465  			unmarshalled: &btcjson.GetReceivedByAddressCmd{
   466  				Address: "1Address",
   467  				MinConf: btcjson.Int(1),
   468  			},
   469  		},
   470  		{
   471  			name: "getreceivedbyaddress optional",
   472  			newCmd: func() (interface{}, error) {
   473  				return btcjson.NewCmd("getreceivedbyaddress", "1Address", 6)
   474  			},
   475  			staticCmd: func() interface{} {
   476  				return btcjson.NewGetReceivedByAddressCmd("1Address", btcjson.Int(6))
   477  			},
   478  			marshalled: `{"jsonrpc":"1.0","method":"getreceivedbyaddress","params":["1Address",6],"id":1}`,
   479  			unmarshalled: &btcjson.GetReceivedByAddressCmd{
   480  				Address: "1Address",
   481  				MinConf: btcjson.Int(6),
   482  			},
   483  		},
   484  		{
   485  			name: "gettransaction",
   486  			newCmd: func() (interface{}, error) {
   487  				return btcjson.NewCmd("gettransaction", "123")
   488  			},
   489  			staticCmd: func() interface{} {
   490  				return btcjson.NewGetTransactionCmd("123", nil)
   491  			},
   492  			marshalled: `{"jsonrpc":"1.0","method":"gettransaction","params":["123"],"id":1}`,
   493  			unmarshalled: &btcjson.GetTransactionCmd{
   494  				Txid:             "123",
   495  				IncludeWatchOnly: btcjson.Bool(false),
   496  			},
   497  		},
   498  		{
   499  			name: "gettransaction optional",
   500  			newCmd: func() (interface{}, error) {
   501  				return btcjson.NewCmd("gettransaction", "123", true)
   502  			},
   503  			staticCmd: func() interface{} {
   504  				return btcjson.NewGetTransactionCmd("123", btcjson.Bool(true))
   505  			},
   506  			marshalled: `{"jsonrpc":"1.0","method":"gettransaction","params":["123",true],"id":1}`,
   507  			unmarshalled: &btcjson.GetTransactionCmd{
   508  				Txid:             "123",
   509  				IncludeWatchOnly: btcjson.Bool(true),
   510  			},
   511  		},
   512  		{
   513  			name: "getwalletinfo",
   514  			newCmd: func() (interface{}, error) {
   515  				return btcjson.NewCmd("getwalletinfo")
   516  			},
   517  			staticCmd: func() interface{} {
   518  				return btcjson.NewGetWalletInfoCmd()
   519  			},
   520  			marshalled:   `{"jsonrpc":"1.0","method":"getwalletinfo","params":[],"id":1}`,
   521  			unmarshalled: &btcjson.GetWalletInfoCmd{},
   522  		},
   523  		{
   524  			name: "importprivkey",
   525  			newCmd: func() (interface{}, error) {
   526  				return btcjson.NewCmd("importprivkey", "abc")
   527  			},
   528  			staticCmd: func() interface{} {
   529  				return btcjson.NewImportPrivKeyCmd("abc", nil, nil)
   530  			},
   531  			marshalled: `{"jsonrpc":"1.0","method":"importprivkey","params":["abc"],"id":1}`,
   532  			unmarshalled: &btcjson.ImportPrivKeyCmd{
   533  				PrivKey: "abc",
   534  				Label:   nil,
   535  				Rescan:  btcjson.Bool(true),
   536  			},
   537  		},
   538  		{
   539  			name: "importprivkey optional1",
   540  			newCmd: func() (interface{}, error) {
   541  				return btcjson.NewCmd("importprivkey", "abc", "label")
   542  			},
   543  			staticCmd: func() interface{} {
   544  				return btcjson.NewImportPrivKeyCmd("abc", btcjson.String("label"), nil)
   545  			},
   546  			marshalled: `{"jsonrpc":"1.0","method":"importprivkey","params":["abc","label"],"id":1}`,
   547  			unmarshalled: &btcjson.ImportPrivKeyCmd{
   548  				PrivKey: "abc",
   549  				Label:   btcjson.String("label"),
   550  				Rescan:  btcjson.Bool(true),
   551  			},
   552  		},
   553  		{
   554  			name: "importprivkey optional2",
   555  			newCmd: func() (interface{}, error) {
   556  				return btcjson.NewCmd("importprivkey", "abc", "label", false)
   557  			},
   558  			staticCmd: func() interface{} {
   559  				return btcjson.NewImportPrivKeyCmd("abc", btcjson.String("label"), btcjson.Bool(false))
   560  			},
   561  			marshalled: `{"jsonrpc":"1.0","method":"importprivkey","params":["abc","label",false],"id":1}`,
   562  			unmarshalled: &btcjson.ImportPrivKeyCmd{
   563  				PrivKey: "abc",
   564  				Label:   btcjson.String("label"),
   565  				Rescan:  btcjson.Bool(false),
   566  			},
   567  		},
   568  		{
   569  			name: "keypoolrefill",
   570  			newCmd: func() (interface{}, error) {
   571  				return btcjson.NewCmd("keypoolrefill")
   572  			},
   573  			staticCmd: func() interface{} {
   574  				return btcjson.NewKeyPoolRefillCmd(nil)
   575  			},
   576  			marshalled: `{"jsonrpc":"1.0","method":"keypoolrefill","params":[],"id":1}`,
   577  			unmarshalled: &btcjson.KeyPoolRefillCmd{
   578  				NewSize: btcjson.Uint(100),
   579  			},
   580  		},
   581  		{
   582  			name: "keypoolrefill optional",
   583  			newCmd: func() (interface{}, error) {
   584  				return btcjson.NewCmd("keypoolrefill", 200)
   585  			},
   586  			staticCmd: func() interface{} {
   587  				return btcjson.NewKeyPoolRefillCmd(btcjson.Uint(200))
   588  			},
   589  			marshalled: `{"jsonrpc":"1.0","method":"keypoolrefill","params":[200],"id":1}`,
   590  			unmarshalled: &btcjson.KeyPoolRefillCmd{
   591  				NewSize: btcjson.Uint(200),
   592  			},
   593  		},
   594  		{
   595  			name: "listaccounts",
   596  			newCmd: func() (interface{}, error) {
   597  				return btcjson.NewCmd("listaccounts")
   598  			},
   599  			staticCmd: func() interface{} {
   600  				return btcjson.NewListAccountsCmd(nil)
   601  			},
   602  			marshalled: `{"jsonrpc":"1.0","method":"listaccounts","params":[],"id":1}`,
   603  			unmarshalled: &btcjson.ListAccountsCmd{
   604  				MinConf: btcjson.Int(1),
   605  			},
   606  		},
   607  		{
   608  			name: "listaccounts optional",
   609  			newCmd: func() (interface{}, error) {
   610  				return btcjson.NewCmd("listaccounts", 6)
   611  			},
   612  			staticCmd: func() interface{} {
   613  				return btcjson.NewListAccountsCmd(btcjson.Int(6))
   614  			},
   615  			marshalled: `{"jsonrpc":"1.0","method":"listaccounts","params":[6],"id":1}`,
   616  			unmarshalled: &btcjson.ListAccountsCmd{
   617  				MinConf: btcjson.Int(6),
   618  			},
   619  		},
   620  		{
   621  			name: "listaddressgroupings",
   622  			newCmd: func() (interface{}, error) {
   623  				return btcjson.NewCmd("listaddressgroupings")
   624  			},
   625  			staticCmd: func() interface{} {
   626  				return btcjson.NewListAddressGroupingsCmd()
   627  			},
   628  			marshalled:   `{"jsonrpc":"1.0","method":"listaddressgroupings","params":[],"id":1}`,
   629  			unmarshalled: &btcjson.ListAddressGroupingsCmd{},
   630  		},
   631  		{
   632  			name: "listlockunspent",
   633  			newCmd: func() (interface{}, error) {
   634  				return btcjson.NewCmd("listlockunspent")
   635  			},
   636  			staticCmd: func() interface{} {
   637  				return btcjson.NewListLockUnspentCmd()
   638  			},
   639  			marshalled:   `{"jsonrpc":"1.0","method":"listlockunspent","params":[],"id":1}`,
   640  			unmarshalled: &btcjson.ListLockUnspentCmd{},
   641  		},
   642  		{
   643  			name: "listreceivedbyaccount",
   644  			newCmd: func() (interface{}, error) {
   645  				return btcjson.NewCmd("listreceivedbyaccount")
   646  			},
   647  			staticCmd: func() interface{} {
   648  				return btcjson.NewListReceivedByAccountCmd(nil, nil, nil)
   649  			},
   650  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[],"id":1}`,
   651  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   652  				MinConf:          btcjson.Int(1),
   653  				IncludeEmpty:     btcjson.Bool(false),
   654  				IncludeWatchOnly: btcjson.Bool(false),
   655  			},
   656  		},
   657  		{
   658  			name: "listreceivedbyaccount optional1",
   659  			newCmd: func() (interface{}, error) {
   660  				return btcjson.NewCmd("listreceivedbyaccount", 6)
   661  			},
   662  			staticCmd: func() interface{} {
   663  				return btcjson.NewListReceivedByAccountCmd(btcjson.Int(6), nil, nil)
   664  			},
   665  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[6],"id":1}`,
   666  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   667  				MinConf:          btcjson.Int(6),
   668  				IncludeEmpty:     btcjson.Bool(false),
   669  				IncludeWatchOnly: btcjson.Bool(false),
   670  			},
   671  		},
   672  		{
   673  			name: "listreceivedbyaccount optional2",
   674  			newCmd: func() (interface{}, error) {
   675  				return btcjson.NewCmd("listreceivedbyaccount", 6, true)
   676  			},
   677  			staticCmd: func() interface{} {
   678  				return btcjson.NewListReceivedByAccountCmd(btcjson.Int(6), btcjson.Bool(true), nil)
   679  			},
   680  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[6,true],"id":1}`,
   681  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   682  				MinConf:          btcjson.Int(6),
   683  				IncludeEmpty:     btcjson.Bool(true),
   684  				IncludeWatchOnly: btcjson.Bool(false),
   685  			},
   686  		},
   687  		{
   688  			name: "listreceivedbyaccount optional3",
   689  			newCmd: func() (interface{}, error) {
   690  				return btcjson.NewCmd("listreceivedbyaccount", 6, true, false)
   691  			},
   692  			staticCmd: func() interface{} {
   693  				return btcjson.NewListReceivedByAccountCmd(btcjson.Int(6), btcjson.Bool(true), btcjson.Bool(false))
   694  			},
   695  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaccount","params":[6,true,false],"id":1}`,
   696  			unmarshalled: &btcjson.ListReceivedByAccountCmd{
   697  				MinConf:          btcjson.Int(6),
   698  				IncludeEmpty:     btcjson.Bool(true),
   699  				IncludeWatchOnly: btcjson.Bool(false),
   700  			},
   701  		},
   702  		{
   703  			name: "listreceivedbyaddress",
   704  			newCmd: func() (interface{}, error) {
   705  				return btcjson.NewCmd("listreceivedbyaddress")
   706  			},
   707  			staticCmd: func() interface{} {
   708  				return btcjson.NewListReceivedByAddressCmd(nil, nil, nil)
   709  			},
   710  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[],"id":1}`,
   711  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   712  				MinConf:          btcjson.Int(1),
   713  				IncludeEmpty:     btcjson.Bool(false),
   714  				IncludeWatchOnly: btcjson.Bool(false),
   715  			},
   716  		},
   717  		{
   718  			name: "listreceivedbyaddress optional1",
   719  			newCmd: func() (interface{}, error) {
   720  				return btcjson.NewCmd("listreceivedbyaddress", 6)
   721  			},
   722  			staticCmd: func() interface{} {
   723  				return btcjson.NewListReceivedByAddressCmd(btcjson.Int(6), nil, nil)
   724  			},
   725  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[6],"id":1}`,
   726  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   727  				MinConf:          btcjson.Int(6),
   728  				IncludeEmpty:     btcjson.Bool(false),
   729  				IncludeWatchOnly: btcjson.Bool(false),
   730  			},
   731  		},
   732  		{
   733  			name: "listreceivedbyaddress optional2",
   734  			newCmd: func() (interface{}, error) {
   735  				return btcjson.NewCmd("listreceivedbyaddress", 6, true)
   736  			},
   737  			staticCmd: func() interface{} {
   738  				return btcjson.NewListReceivedByAddressCmd(btcjson.Int(6), btcjson.Bool(true), nil)
   739  			},
   740  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[6,true],"id":1}`,
   741  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   742  				MinConf:          btcjson.Int(6),
   743  				IncludeEmpty:     btcjson.Bool(true),
   744  				IncludeWatchOnly: btcjson.Bool(false),
   745  			},
   746  		},
   747  		{
   748  			name: "listreceivedbyaddress optional3",
   749  			newCmd: func() (interface{}, error) {
   750  				return btcjson.NewCmd("listreceivedbyaddress", 6, true, false)
   751  			},
   752  			staticCmd: func() interface{} {
   753  				return btcjson.NewListReceivedByAddressCmd(btcjson.Int(6), btcjson.Bool(true), btcjson.Bool(false))
   754  			},
   755  			marshalled: `{"jsonrpc":"1.0","method":"listreceivedbyaddress","params":[6,true,false],"id":1}`,
   756  			unmarshalled: &btcjson.ListReceivedByAddressCmd{
   757  				MinConf:          btcjson.Int(6),
   758  				IncludeEmpty:     btcjson.Bool(true),
   759  				IncludeWatchOnly: btcjson.Bool(false),
   760  			},
   761  		},
   762  		{
   763  			name: "listsinceblock",
   764  			newCmd: func() (interface{}, error) {
   765  				return btcjson.NewCmd("listsinceblock")
   766  			},
   767  			staticCmd: func() interface{} {
   768  				return btcjson.NewListSinceBlockCmd(nil, nil, nil)
   769  			},
   770  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":[],"id":1}`,
   771  			unmarshalled: &btcjson.ListSinceBlockCmd{
   772  				BlockHash:           nil,
   773  				TargetConfirmations: btcjson.Int(1),
   774  				IncludeWatchOnly:    btcjson.Bool(false),
   775  			},
   776  		},
   777  		{
   778  			name: "listsinceblock optional1",
   779  			newCmd: func() (interface{}, error) {
   780  				return btcjson.NewCmd("listsinceblock", "123")
   781  			},
   782  			staticCmd: func() interface{} {
   783  				return btcjson.NewListSinceBlockCmd(btcjson.String("123"), nil, nil)
   784  			},
   785  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":["123"],"id":1}`,
   786  			unmarshalled: &btcjson.ListSinceBlockCmd{
   787  				BlockHash:           btcjson.String("123"),
   788  				TargetConfirmations: btcjson.Int(1),
   789  				IncludeWatchOnly:    btcjson.Bool(false),
   790  			},
   791  		},
   792  		{
   793  			name: "listsinceblock optional2",
   794  			newCmd: func() (interface{}, error) {
   795  				return btcjson.NewCmd("listsinceblock", "123", 6)
   796  			},
   797  			staticCmd: func() interface{} {
   798  				return btcjson.NewListSinceBlockCmd(btcjson.String("123"), btcjson.Int(6), nil)
   799  			},
   800  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":["123",6],"id":1}`,
   801  			unmarshalled: &btcjson.ListSinceBlockCmd{
   802  				BlockHash:           btcjson.String("123"),
   803  				TargetConfirmations: btcjson.Int(6),
   804  				IncludeWatchOnly:    btcjson.Bool(false),
   805  			},
   806  		},
   807  		{
   808  			name: "listsinceblock optional3",
   809  			newCmd: func() (interface{}, error) {
   810  				return btcjson.NewCmd("listsinceblock", "123", 6, true)
   811  			},
   812  			staticCmd: func() interface{} {
   813  				return btcjson.NewListSinceBlockCmd(btcjson.String("123"), btcjson.Int(6), btcjson.Bool(true))
   814  			},
   815  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":["123",6,true],"id":1}`,
   816  			unmarshalled: &btcjson.ListSinceBlockCmd{
   817  				BlockHash:           btcjson.String("123"),
   818  				TargetConfirmations: btcjson.Int(6),
   819  				IncludeWatchOnly:    btcjson.Bool(true),
   820  			},
   821  		},
   822  		{
   823  			name: "listsinceblock pad null",
   824  			newCmd: func() (interface{}, error) {
   825  				return btcjson.NewCmd("listsinceblock", "null", 1, false)
   826  			},
   827  			staticCmd: func() interface{} {
   828  				return btcjson.NewListSinceBlockCmd(nil, btcjson.Int(1), btcjson.Bool(false))
   829  			},
   830  			marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":[null,1,false],"id":1}`,
   831  			unmarshalled: &btcjson.ListSinceBlockCmd{
   832  				BlockHash:           nil,
   833  				TargetConfirmations: btcjson.Int(1),
   834  				IncludeWatchOnly:    btcjson.Bool(false),
   835  			},
   836  		},
   837  		{
   838  			name: "listtransactions",
   839  			newCmd: func() (interface{}, error) {
   840  				return btcjson.NewCmd("listtransactions")
   841  			},
   842  			staticCmd: func() interface{} {
   843  				return btcjson.NewListTransactionsCmd(nil, nil, nil, nil)
   844  			},
   845  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":[],"id":1}`,
   846  			unmarshalled: &btcjson.ListTransactionsCmd{
   847  				Account:          nil,
   848  				Count:            btcjson.Int(10),
   849  				From:             btcjson.Int(0),
   850  				IncludeWatchOnly: btcjson.Bool(false),
   851  			},
   852  		},
   853  		{
   854  			name: "listtransactions optional1",
   855  			newCmd: func() (interface{}, error) {
   856  				return btcjson.NewCmd("listtransactions", "acct")
   857  			},
   858  			staticCmd: func() interface{} {
   859  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), nil, nil, nil)
   860  			},
   861  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct"],"id":1}`,
   862  			unmarshalled: &btcjson.ListTransactionsCmd{
   863  				Account:          btcjson.String("acct"),
   864  				Count:            btcjson.Int(10),
   865  				From:             btcjson.Int(0),
   866  				IncludeWatchOnly: btcjson.Bool(false),
   867  			},
   868  		},
   869  		{
   870  			name: "listtransactions optional2",
   871  			newCmd: func() (interface{}, error) {
   872  				return btcjson.NewCmd("listtransactions", "acct", 20)
   873  			},
   874  			staticCmd: func() interface{} {
   875  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), btcjson.Int(20), nil, nil)
   876  			},
   877  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct",20],"id":1}`,
   878  			unmarshalled: &btcjson.ListTransactionsCmd{
   879  				Account:          btcjson.String("acct"),
   880  				Count:            btcjson.Int(20),
   881  				From:             btcjson.Int(0),
   882  				IncludeWatchOnly: btcjson.Bool(false),
   883  			},
   884  		},
   885  		{
   886  			name: "listtransactions optional3",
   887  			newCmd: func() (interface{}, error) {
   888  				return btcjson.NewCmd("listtransactions", "acct", 20, 1)
   889  			},
   890  			staticCmd: func() interface{} {
   891  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), btcjson.Int(20),
   892  					btcjson.Int(1), nil)
   893  			},
   894  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct",20,1],"id":1}`,
   895  			unmarshalled: &btcjson.ListTransactionsCmd{
   896  				Account:          btcjson.String("acct"),
   897  				Count:            btcjson.Int(20),
   898  				From:             btcjson.Int(1),
   899  				IncludeWatchOnly: btcjson.Bool(false),
   900  			},
   901  		},
   902  		{
   903  			name: "listtransactions optional4",
   904  			newCmd: func() (interface{}, error) {
   905  				return btcjson.NewCmd("listtransactions", "acct", 20, 1, true)
   906  			},
   907  			staticCmd: func() interface{} {
   908  				return btcjson.NewListTransactionsCmd(btcjson.String("acct"), btcjson.Int(20),
   909  					btcjson.Int(1), btcjson.Bool(true))
   910  			},
   911  			marshalled: `{"jsonrpc":"1.0","method":"listtransactions","params":["acct",20,1,true],"id":1}`,
   912  			unmarshalled: &btcjson.ListTransactionsCmd{
   913  				Account:          btcjson.String("acct"),
   914  				Count:            btcjson.Int(20),
   915  				From:             btcjson.Int(1),
   916  				IncludeWatchOnly: btcjson.Bool(true),
   917  			},
   918  		},
   919  		{
   920  			name: "listunspent",
   921  			newCmd: func() (interface{}, error) {
   922  				return btcjson.NewCmd("listunspent")
   923  			},
   924  			staticCmd: func() interface{} {
   925  				return btcjson.NewListUnspentCmd(nil, nil, nil)
   926  			},
   927  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[],"id":1}`,
   928  			unmarshalled: &btcjson.ListUnspentCmd{
   929  				MinConf:   btcjson.Int(1),
   930  				MaxConf:   btcjson.Int(9999999),
   931  				Addresses: nil,
   932  			},
   933  		},
   934  		{
   935  			name: "listunspent optional1",
   936  			newCmd: func() (interface{}, error) {
   937  				return btcjson.NewCmd("listunspent", 6)
   938  			},
   939  			staticCmd: func() interface{} {
   940  				return btcjson.NewListUnspentCmd(btcjson.Int(6), nil, nil)
   941  			},
   942  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[6],"id":1}`,
   943  			unmarshalled: &btcjson.ListUnspentCmd{
   944  				MinConf:   btcjson.Int(6),
   945  				MaxConf:   btcjson.Int(9999999),
   946  				Addresses: nil,
   947  			},
   948  		},
   949  		{
   950  			name: "listunspent optional2",
   951  			newCmd: func() (interface{}, error) {
   952  				return btcjson.NewCmd("listunspent", 6, 100)
   953  			},
   954  			staticCmd: func() interface{} {
   955  				return btcjson.NewListUnspentCmd(btcjson.Int(6), btcjson.Int(100), nil)
   956  			},
   957  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[6,100],"id":1}`,
   958  			unmarshalled: &btcjson.ListUnspentCmd{
   959  				MinConf:   btcjson.Int(6),
   960  				MaxConf:   btcjson.Int(100),
   961  				Addresses: nil,
   962  			},
   963  		},
   964  		{
   965  			name: "listunspent optional3",
   966  			newCmd: func() (interface{}, error) {
   967  				return btcjson.NewCmd("listunspent", 6, 100, []string{"1Address", "1Address2"})
   968  			},
   969  			staticCmd: func() interface{} {
   970  				return btcjson.NewListUnspentCmd(btcjson.Int(6), btcjson.Int(100),
   971  					&[]string{"1Address", "1Address2"})
   972  			},
   973  			marshalled: `{"jsonrpc":"1.0","method":"listunspent","params":[6,100,["1Address","1Address2"]],"id":1}`,
   974  			unmarshalled: &btcjson.ListUnspentCmd{
   975  				MinConf:   btcjson.Int(6),
   976  				MaxConf:   btcjson.Int(100),
   977  				Addresses: &[]string{"1Address", "1Address2"},
   978  			},
   979  		},
   980  		{
   981  			name: "lockunspent",
   982  			newCmd: func() (interface{}, error) {
   983  				return btcjson.NewCmd("lockunspent", true, `[{"txid":"123","vout":1}]`)
   984  			},
   985  			staticCmd: func() interface{} {
   986  				txInputs := []btcjson.TransactionInput{
   987  					{Txid: "123", Vout: 1},
   988  				}
   989  				return btcjson.NewLockUnspentCmd(true, txInputs)
   990  			},
   991  			marshalled: `{"jsonrpc":"1.0","method":"lockunspent","params":[true,[{"txid":"123","vout":1}]],"id":1}`,
   992  			unmarshalled: &btcjson.LockUnspentCmd{
   993  				Unlock: true,
   994  				Transactions: []btcjson.TransactionInput{
   995  					{Txid: "123", Vout: 1},
   996  				},
   997  			},
   998  		},
   999  		{
  1000  			name: "move",
  1001  			newCmd: func() (interface{}, error) {
  1002  				return btcjson.NewCmd("move", "from", "to", 0.5)
  1003  			},
  1004  			staticCmd: func() interface{} {
  1005  				return btcjson.NewMoveCmd("from", "to", 0.5, nil, nil)
  1006  			},
  1007  			marshalled: `{"jsonrpc":"1.0","method":"move","params":["from","to",0.5],"id":1}`,
  1008  			unmarshalled: &btcjson.MoveCmd{
  1009  				FromAccount: "from",
  1010  				ToAccount:   "to",
  1011  				Amount:      0.5,
  1012  				MinConf:     btcjson.Int(1),
  1013  				Comment:     nil,
  1014  			},
  1015  		},
  1016  		{
  1017  			name: "move optional1",
  1018  			newCmd: func() (interface{}, error) {
  1019  				return btcjson.NewCmd("move", "from", "to", 0.5, 6)
  1020  			},
  1021  			staticCmd: func() interface{} {
  1022  				return btcjson.NewMoveCmd("from", "to", 0.5, btcjson.Int(6), nil)
  1023  			},
  1024  			marshalled: `{"jsonrpc":"1.0","method":"move","params":["from","to",0.5,6],"id":1}`,
  1025  			unmarshalled: &btcjson.MoveCmd{
  1026  				FromAccount: "from",
  1027  				ToAccount:   "to",
  1028  				Amount:      0.5,
  1029  				MinConf:     btcjson.Int(6),
  1030  				Comment:     nil,
  1031  			},
  1032  		},
  1033  		{
  1034  			name: "move optional2",
  1035  			newCmd: func() (interface{}, error) {
  1036  				return btcjson.NewCmd("move", "from", "to", 0.5, 6, "comment")
  1037  			},
  1038  			staticCmd: func() interface{} {
  1039  				return btcjson.NewMoveCmd("from", "to", 0.5, btcjson.Int(6), btcjson.String("comment"))
  1040  			},
  1041  			marshalled: `{"jsonrpc":"1.0","method":"move","params":["from","to",0.5,6,"comment"],"id":1}`,
  1042  			unmarshalled: &btcjson.MoveCmd{
  1043  				FromAccount: "from",
  1044  				ToAccount:   "to",
  1045  				Amount:      0.5,
  1046  				MinConf:     btcjson.Int(6),
  1047  				Comment:     btcjson.String("comment"),
  1048  			},
  1049  		},
  1050  		{
  1051  			name: "sendfrom",
  1052  			newCmd: func() (interface{}, error) {
  1053  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5)
  1054  			},
  1055  			staticCmd: func() interface{} {
  1056  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, nil, nil, nil)
  1057  			},
  1058  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5],"id":1}`,
  1059  			unmarshalled: &btcjson.SendFromCmd{
  1060  				FromAccount: "from",
  1061  				ToAddress:   "1Address",
  1062  				Amount:      0.5,
  1063  				MinConf:     btcjson.Int(1),
  1064  				Comment:     nil,
  1065  				CommentTo:   nil,
  1066  			},
  1067  		},
  1068  		{
  1069  			name: "sendfrom optional1",
  1070  			newCmd: func() (interface{}, error) {
  1071  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5, 6)
  1072  			},
  1073  			staticCmd: func() interface{} {
  1074  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, btcjson.Int(6), nil, nil)
  1075  			},
  1076  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5,6],"id":1}`,
  1077  			unmarshalled: &btcjson.SendFromCmd{
  1078  				FromAccount: "from",
  1079  				ToAddress:   "1Address",
  1080  				Amount:      0.5,
  1081  				MinConf:     btcjson.Int(6),
  1082  				Comment:     nil,
  1083  				CommentTo:   nil,
  1084  			},
  1085  		},
  1086  		{
  1087  			name: "sendfrom optional2",
  1088  			newCmd: func() (interface{}, error) {
  1089  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5, 6, "comment")
  1090  			},
  1091  			staticCmd: func() interface{} {
  1092  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, btcjson.Int(6),
  1093  					btcjson.String("comment"), nil)
  1094  			},
  1095  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5,6,"comment"],"id":1}`,
  1096  			unmarshalled: &btcjson.SendFromCmd{
  1097  				FromAccount: "from",
  1098  				ToAddress:   "1Address",
  1099  				Amount:      0.5,
  1100  				MinConf:     btcjson.Int(6),
  1101  				Comment:     btcjson.String("comment"),
  1102  				CommentTo:   nil,
  1103  			},
  1104  		},
  1105  		{
  1106  			name: "sendfrom optional3",
  1107  			newCmd: func() (interface{}, error) {
  1108  				return btcjson.NewCmd("sendfrom", "from", "1Address", 0.5, 6, "comment", "commentto")
  1109  			},
  1110  			staticCmd: func() interface{} {
  1111  				return btcjson.NewSendFromCmd("from", "1Address", 0.5, btcjson.Int(6),
  1112  					btcjson.String("comment"), btcjson.String("commentto"))
  1113  			},
  1114  			marshalled: `{"jsonrpc":"1.0","method":"sendfrom","params":["from","1Address",0.5,6,"comment","commentto"],"id":1}`,
  1115  			unmarshalled: &btcjson.SendFromCmd{
  1116  				FromAccount: "from",
  1117  				ToAddress:   "1Address",
  1118  				Amount:      0.5,
  1119  				MinConf:     btcjson.Int(6),
  1120  				Comment:     btcjson.String("comment"),
  1121  				CommentTo:   btcjson.String("commentto"),
  1122  			},
  1123  		},
  1124  		{
  1125  			name: "sendmany",
  1126  			newCmd: func() (interface{}, error) {
  1127  				return btcjson.NewCmd("sendmany", "from", `{"1Address":0.5}`)
  1128  			},
  1129  			staticCmd: func() interface{} {
  1130  				amounts := map[string]float64{"1Address": 0.5}
  1131  				return btcjson.NewSendManyCmd("from", amounts, nil, nil)
  1132  			},
  1133  			marshalled: `{"jsonrpc":"1.0","method":"sendmany","params":["from",{"1Address":0.5}],"id":1}`,
  1134  			unmarshalled: &btcjson.SendManyCmd{
  1135  				FromAccount: "from",
  1136  				Amounts:     map[string]float64{"1Address": 0.5},
  1137  				MinConf:     btcjson.Int(1),
  1138  				Comment:     nil,
  1139  			},
  1140  		},
  1141  		{
  1142  			name: "sendmany optional1",
  1143  			newCmd: func() (interface{}, error) {
  1144  				return btcjson.NewCmd("sendmany", "from", `{"1Address":0.5}`, 6)
  1145  			},
  1146  			staticCmd: func() interface{} {
  1147  				amounts := map[string]float64{"1Address": 0.5}
  1148  				return btcjson.NewSendManyCmd("from", amounts, btcjson.Int(6), nil)
  1149  			},
  1150  			marshalled: `{"jsonrpc":"1.0","method":"sendmany","params":["from",{"1Address":0.5},6],"id":1}`,
  1151  			unmarshalled: &btcjson.SendManyCmd{
  1152  				FromAccount: "from",
  1153  				Amounts:     map[string]float64{"1Address": 0.5},
  1154  				MinConf:     btcjson.Int(6),
  1155  				Comment:     nil,
  1156  			},
  1157  		},
  1158  		{
  1159  			name: "sendmany optional2",
  1160  			newCmd: func() (interface{}, error) {
  1161  				return btcjson.NewCmd("sendmany", "from", `{"1Address":0.5}`, 6, "comment")
  1162  			},
  1163  			staticCmd: func() interface{} {
  1164  				amounts := map[string]float64{"1Address": 0.5}
  1165  				return btcjson.NewSendManyCmd("from", amounts, btcjson.Int(6), btcjson.String("comment"))
  1166  			},
  1167  			marshalled: `{"jsonrpc":"1.0","method":"sendmany","params":["from",{"1Address":0.5},6,"comment"],"id":1}`,
  1168  			unmarshalled: &btcjson.SendManyCmd{
  1169  				FromAccount: "from",
  1170  				Amounts:     map[string]float64{"1Address": 0.5},
  1171  				MinConf:     btcjson.Int(6),
  1172  				Comment:     btcjson.String("comment"),
  1173  			},
  1174  		},
  1175  		{
  1176  			name: "sendtoaddress",
  1177  			newCmd: func() (interface{}, error) {
  1178  				return btcjson.NewCmd("sendtoaddress", "1Address", 0.5)
  1179  			},
  1180  			staticCmd: func() interface{} {
  1181  				return btcjson.NewSendToAddressCmd("1Address", 0.5, nil, nil)
  1182  			},
  1183  			marshalled: `{"jsonrpc":"1.0","method":"sendtoaddress","params":["1Address",0.5],"id":1}`,
  1184  			unmarshalled: &btcjson.SendToAddressCmd{
  1185  				Address:   "1Address",
  1186  				Amount:    0.5,
  1187  				Comment:   nil,
  1188  				CommentTo: nil,
  1189  			},
  1190  		},
  1191  		{
  1192  			name: "sendtoaddress optional1",
  1193  			newCmd: func() (interface{}, error) {
  1194  				return btcjson.NewCmd("sendtoaddress", "1Address", 0.5, "comment", "commentto")
  1195  			},
  1196  			staticCmd: func() interface{} {
  1197  				return btcjson.NewSendToAddressCmd("1Address", 0.5, btcjson.String("comment"),
  1198  					btcjson.String("commentto"))
  1199  			},
  1200  			marshalled: `{"jsonrpc":"1.0","method":"sendtoaddress","params":["1Address",0.5,"comment","commentto"],"id":1}`,
  1201  			unmarshalled: &btcjson.SendToAddressCmd{
  1202  				Address:   "1Address",
  1203  				Amount:    0.5,
  1204  				Comment:   btcjson.String("comment"),
  1205  				CommentTo: btcjson.String("commentto"),
  1206  			},
  1207  		},
  1208  		{
  1209  			name: "setaccount",
  1210  			newCmd: func() (interface{}, error) {
  1211  				return btcjson.NewCmd("setaccount", "1Address", "acct")
  1212  			},
  1213  			staticCmd: func() interface{} {
  1214  				return btcjson.NewSetAccountCmd("1Address", "acct")
  1215  			},
  1216  			marshalled: `{"jsonrpc":"1.0","method":"setaccount","params":["1Address","acct"],"id":1}`,
  1217  			unmarshalled: &btcjson.SetAccountCmd{
  1218  				Address: "1Address",
  1219  				Account: "acct",
  1220  			},
  1221  		},
  1222  		{
  1223  			name: "settxfee",
  1224  			newCmd: func() (interface{}, error) {
  1225  				return btcjson.NewCmd("settxfee", 0.0001)
  1226  			},
  1227  			staticCmd: func() interface{} {
  1228  				return btcjson.NewSetTxFeeCmd(0.0001)
  1229  			},
  1230  			marshalled: `{"jsonrpc":"1.0","method":"settxfee","params":[0.0001],"id":1}`,
  1231  			unmarshalled: &btcjson.SetTxFeeCmd{
  1232  				Amount: 0.0001,
  1233  			},
  1234  		},
  1235  		{
  1236  			name: "signmessage",
  1237  			newCmd: func() (interface{}, error) {
  1238  				return btcjson.NewCmd("signmessage", "1Address", "message")
  1239  			},
  1240  			staticCmd: func() interface{} {
  1241  				return btcjson.NewSignMessageCmd("1Address", "message")
  1242  			},
  1243  			marshalled: `{"jsonrpc":"1.0","method":"signmessage","params":["1Address","message"],"id":1}`,
  1244  			unmarshalled: &btcjson.SignMessageCmd{
  1245  				Address: "1Address",
  1246  				Message: "message",
  1247  			},
  1248  		},
  1249  		{
  1250  			name: "signrawtransaction",
  1251  			newCmd: func() (interface{}, error) {
  1252  				return btcjson.NewCmd("signrawtransaction", "001122")
  1253  			},
  1254  			staticCmd: func() interface{} {
  1255  				return btcjson.NewSignRawTransactionCmd("001122", nil, nil, nil)
  1256  			},
  1257  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122"],"id":1}`,
  1258  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1259  				RawTx:    "001122",
  1260  				Inputs:   nil,
  1261  				PrivKeys: nil,
  1262  				Flags:    btcjson.String("ALL"),
  1263  			},
  1264  		},
  1265  		{
  1266  			name: "signrawtransaction optional1",
  1267  			newCmd: func() (interface{}, error) {
  1268  				return btcjson.NewCmd("signrawtransaction", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]`)
  1269  			},
  1270  			staticCmd: func() interface{} {
  1271  				txInputs := []btcjson.RawTxInput{
  1272  					{
  1273  						Txid:         "123",
  1274  						Vout:         1,
  1275  						ScriptPubKey: "00",
  1276  						RedeemScript: "01",
  1277  					},
  1278  				}
  1279  
  1280  				return btcjson.NewSignRawTransactionCmd("001122", &txInputs, nil, nil)
  1281  			},
  1282  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]],"id":1}`,
  1283  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1284  				RawTx: "001122",
  1285  				Inputs: &[]btcjson.RawTxInput{
  1286  					{
  1287  						Txid:         "123",
  1288  						Vout:         1,
  1289  						ScriptPubKey: "00",
  1290  						RedeemScript: "01",
  1291  					},
  1292  				},
  1293  				PrivKeys: nil,
  1294  				Flags:    btcjson.String("ALL"),
  1295  			},
  1296  		},
  1297  		{
  1298  			name: "signrawtransaction optional2",
  1299  			newCmd: func() (interface{}, error) {
  1300  				return btcjson.NewCmd("signrawtransaction", "001122", `[]`, `["abc"]`)
  1301  			},
  1302  			staticCmd: func() interface{} {
  1303  				txInputs := []btcjson.RawTxInput{}
  1304  				privKeys := []string{"abc"}
  1305  				return btcjson.NewSignRawTransactionCmd("001122", &txInputs, &privKeys, nil)
  1306  			},
  1307  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122",[],["abc"]],"id":1}`,
  1308  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1309  				RawTx:    "001122",
  1310  				Inputs:   &[]btcjson.RawTxInput{},
  1311  				PrivKeys: &[]string{"abc"},
  1312  				Flags:    btcjson.String("ALL"),
  1313  			},
  1314  		},
  1315  		{
  1316  			name: "signrawtransaction optional3",
  1317  			newCmd: func() (interface{}, error) {
  1318  				return btcjson.NewCmd("signrawtransaction", "001122", `[]`, `[]`, "ALL")
  1319  			},
  1320  			staticCmd: func() interface{} {
  1321  				txInputs := []btcjson.RawTxInput{}
  1322  				privKeys := []string{}
  1323  				return btcjson.NewSignRawTransactionCmd("001122", &txInputs, &privKeys,
  1324  					btcjson.String("ALL"))
  1325  			},
  1326  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransaction","params":["001122",[],[],"ALL"],"id":1}`,
  1327  			unmarshalled: &btcjson.SignRawTransactionCmd{
  1328  				RawTx:    "001122",
  1329  				Inputs:   &[]btcjson.RawTxInput{},
  1330  				PrivKeys: &[]string{},
  1331  				Flags:    btcjson.String("ALL"),
  1332  			},
  1333  		},
  1334  		{
  1335  			name: "signrawtransactionwithwallet",
  1336  			newCmd: func() (interface{}, error) {
  1337  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122")
  1338  			},
  1339  			staticCmd: func() interface{} {
  1340  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", nil, nil)
  1341  			},
  1342  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122"],"id":1}`,
  1343  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1344  				RawTx:       "001122",
  1345  				Inputs:      nil,
  1346  				SigHashType: btcjson.String("ALL"),
  1347  			},
  1348  		},
  1349  		{
  1350  			name: "signrawtransactionwithwallet optional1",
  1351  			newCmd: func() (interface{}, error) {
  1352  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01","witnessScript":"02","amount":1.5}]`)
  1353  			},
  1354  			staticCmd: func() interface{} {
  1355  				txInputs := []btcjson.RawTxWitnessInput{
  1356  					{
  1357  						Txid:          "123",
  1358  						Vout:          1,
  1359  						ScriptPubKey:  "00",
  1360  						RedeemScript:  btcjson.String("01"),
  1361  						WitnessScript: btcjson.String("02"),
  1362  						Amount:        btcjson.Float64(1.5),
  1363  					},
  1364  				}
  1365  
  1366  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, nil)
  1367  			},
  1368  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01","witnessScript":"02","amount":1.5}]],"id":1}`,
  1369  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1370  				RawTx: "001122",
  1371  				Inputs: &[]btcjson.RawTxWitnessInput{
  1372  					{
  1373  						Txid:          "123",
  1374  						Vout:          1,
  1375  						ScriptPubKey:  "00",
  1376  						RedeemScript:  btcjson.String("01"),
  1377  						WitnessScript: btcjson.String("02"),
  1378  						Amount:        btcjson.Float64(1.5),
  1379  					},
  1380  				},
  1381  				SigHashType: btcjson.String("ALL"),
  1382  			},
  1383  		},
  1384  		{
  1385  			name: "signrawtransactionwithwallet optional1 with blank fields in input",
  1386  			newCmd: func() (interface{}, error) {
  1387  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]`)
  1388  			},
  1389  			staticCmd: func() interface{} {
  1390  				txInputs := []btcjson.RawTxWitnessInput{
  1391  					{
  1392  						Txid:         "123",
  1393  						Vout:         1,
  1394  						ScriptPubKey: "00",
  1395  						RedeemScript: btcjson.String("01"),
  1396  					},
  1397  				}
  1398  
  1399  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, nil)
  1400  			},
  1401  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]],"id":1}`,
  1402  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1403  				RawTx: "001122",
  1404  				Inputs: &[]btcjson.RawTxWitnessInput{
  1405  					{
  1406  						Txid:         "123",
  1407  						Vout:         1,
  1408  						ScriptPubKey: "00",
  1409  						RedeemScript: btcjson.String("01"),
  1410  					},
  1411  				},
  1412  				SigHashType: btcjson.String("ALL"),
  1413  			},
  1414  		},
  1415  		{
  1416  			name: "signrawtransactionwithwallet optional2",
  1417  			newCmd: func() (interface{}, error) {
  1418  				return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[]`, "ALL")
  1419  			},
  1420  			staticCmd: func() interface{} {
  1421  				txInputs := []btcjson.RawTxWitnessInput{}
  1422  				return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, btcjson.String("ALL"))
  1423  			},
  1424  			marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[],"ALL"],"id":1}`,
  1425  			unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{
  1426  				RawTx:       "001122",
  1427  				Inputs:      &[]btcjson.RawTxWitnessInput{},
  1428  				SigHashType: btcjson.String("ALL"),
  1429  			},
  1430  		},
  1431  		{
  1432  			name: "walletlock",
  1433  			newCmd: func() (interface{}, error) {
  1434  				return btcjson.NewCmd("walletlock")
  1435  			},
  1436  			staticCmd: func() interface{} {
  1437  				return btcjson.NewWalletLockCmd()
  1438  			},
  1439  			marshalled:   `{"jsonrpc":"1.0","method":"walletlock","params":[],"id":1}`,
  1440  			unmarshalled: &btcjson.WalletLockCmd{},
  1441  		},
  1442  		{
  1443  			name: "walletpassphrase",
  1444  			newCmd: func() (interface{}, error) {
  1445  				return btcjson.NewCmd("walletpassphrase", "pass", 60)
  1446  			},
  1447  			staticCmd: func() interface{} {
  1448  				return btcjson.NewWalletPassphraseCmd("pass", 60)
  1449  			},
  1450  			marshalled: `{"jsonrpc":"1.0","method":"walletpassphrase","params":["pass",60],"id":1}`,
  1451  			unmarshalled: &btcjson.WalletPassphraseCmd{
  1452  				Passphrase: "pass",
  1453  				Timeout:    60,
  1454  			},
  1455  		},
  1456  		{
  1457  			name: "walletpassphrasechange",
  1458  			newCmd: func() (interface{}, error) {
  1459  				return btcjson.NewCmd("walletpassphrasechange", "old", "new")
  1460  			},
  1461  			staticCmd: func() interface{} {
  1462  				return btcjson.NewWalletPassphraseChangeCmd("old", "new")
  1463  			},
  1464  			marshalled: `{"jsonrpc":"1.0","method":"walletpassphrasechange","params":["old","new"],"id":1}`,
  1465  			unmarshalled: &btcjson.WalletPassphraseChangeCmd{
  1466  				OldPassphrase: "old",
  1467  				NewPassphrase: "new",
  1468  			},
  1469  		},
  1470  		{
  1471  			name: "importmulti with descriptor + options",
  1472  			newCmd: func() (interface{}, error) {
  1473  				return btcjson.NewCmd(
  1474  					"importmulti",
  1475  					// Cannot use a native string, due to special types like timestamp.
  1476  					[]btcjson.ImportMultiRequest{
  1477  						{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: 0}},
  1478  					},
  1479  					`{"rescan": true}`,
  1480  				)
  1481  			},
  1482  			staticCmd: func() interface{} {
  1483  				requests := []btcjson.ImportMultiRequest{
  1484  					{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: 0}},
  1485  				}
  1486  				options := btcjson.ImportMultiOptions{Rescan: true}
  1487  				return btcjson.NewImportMultiCmd(requests, &options)
  1488  			},
  1489  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0}],{"rescan":true}],"id":1}`,
  1490  			unmarshalled: &btcjson.ImportMultiCmd{
  1491  				Requests: []btcjson.ImportMultiRequest{
  1492  					{
  1493  						Descriptor: btcjson.String("123"),
  1494  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1495  					},
  1496  				},
  1497  				Options: &btcjson.ImportMultiOptions{Rescan: true},
  1498  			},
  1499  		},
  1500  		{
  1501  			name: "importmulti with descriptor + no options",
  1502  			newCmd: func() (interface{}, error) {
  1503  				return btcjson.NewCmd(
  1504  					"importmulti",
  1505  					// Cannot use a native string, due to special types like timestamp.
  1506  					[]btcjson.ImportMultiRequest{
  1507  						{
  1508  							Descriptor: btcjson.String("123"),
  1509  							Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1510  							WatchOnly:  btcjson.Bool(false),
  1511  							Internal:   btcjson.Bool(true),
  1512  							Label:      btcjson.String("aaa"),
  1513  							KeyPool:    btcjson.Bool(false),
  1514  						},
  1515  					},
  1516  				)
  1517  			},
  1518  			staticCmd: func() interface{} {
  1519  				requests := []btcjson.ImportMultiRequest{
  1520  					{
  1521  						Descriptor: btcjson.String("123"),
  1522  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1523  						WatchOnly:  btcjson.Bool(false),
  1524  						Internal:   btcjson.Bool(true),
  1525  						Label:      btcjson.String("aaa"),
  1526  						KeyPool:    btcjson.Bool(false),
  1527  					},
  1528  				}
  1529  				return btcjson.NewImportMultiCmd(requests, nil)
  1530  			},
  1531  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"internal":true,"watchonly":false,"label":"aaa","keypool":false}]],"id":1}`,
  1532  			unmarshalled: &btcjson.ImportMultiCmd{
  1533  				Requests: []btcjson.ImportMultiRequest{
  1534  					{
  1535  						Descriptor: btcjson.String("123"),
  1536  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1537  						WatchOnly:  btcjson.Bool(false),
  1538  						Internal:   btcjson.Bool(true),
  1539  						Label:      btcjson.String("aaa"),
  1540  						KeyPool:    btcjson.Bool(false),
  1541  					},
  1542  				},
  1543  			},
  1544  		},
  1545  		{
  1546  			name: "importmulti with descriptor + string timestamp",
  1547  			newCmd: func() (interface{}, error) {
  1548  				return btcjson.NewCmd(
  1549  					"importmulti",
  1550  					// Cannot use a native string, due to special types like timestamp.
  1551  					[]btcjson.ImportMultiRequest{
  1552  						{
  1553  							Descriptor: btcjson.String("123"),
  1554  							Timestamp:  btcjson.TimestampOrNow{Value: "now"},
  1555  						},
  1556  					},
  1557  				)
  1558  			},
  1559  			staticCmd: func() interface{} {
  1560  				requests := []btcjson.ImportMultiRequest{
  1561  					{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: "now"}},
  1562  				}
  1563  				return btcjson.NewImportMultiCmd(requests, nil)
  1564  			},
  1565  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":"now"}]],"id":1}`,
  1566  			unmarshalled: &btcjson.ImportMultiCmd{
  1567  				Requests: []btcjson.ImportMultiRequest{
  1568  					{Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: "now"}},
  1569  				},
  1570  			},
  1571  		},
  1572  		{
  1573  			name: "importmulti with scriptPubKey script",
  1574  			newCmd: func() (interface{}, error) {
  1575  				return btcjson.NewCmd(
  1576  					"importmulti",
  1577  					// Cannot use a native string, due to special types like timestamp and scriptPubKey
  1578  					[]btcjson.ImportMultiRequest{
  1579  						{
  1580  							ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"},
  1581  							RedeemScript: btcjson.String("123"),
  1582  							Timestamp:    btcjson.TimestampOrNow{Value: 0},
  1583  							PubKeys:      &[]string{"aaa"},
  1584  						},
  1585  					},
  1586  				)
  1587  			},
  1588  			staticCmd: func() interface{} {
  1589  				requests := []btcjson.ImportMultiRequest{
  1590  					{
  1591  						ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"},
  1592  						RedeemScript: btcjson.String("123"),
  1593  						Timestamp:    btcjson.TimestampOrNow{Value: 0},
  1594  						PubKeys:      &[]string{"aaa"},
  1595  					},
  1596  				}
  1597  				return btcjson.NewImportMultiCmd(requests, nil)
  1598  			},
  1599  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"scriptPubKey":"script","timestamp":0,"redeemscript":"123","pubkeys":["aaa"]}]],"id":1}`,
  1600  			unmarshalled: &btcjson.ImportMultiCmd{
  1601  				Requests: []btcjson.ImportMultiRequest{
  1602  					{
  1603  						ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"},
  1604  						RedeemScript: btcjson.String("123"),
  1605  						Timestamp:    btcjson.TimestampOrNow{Value: 0},
  1606  						PubKeys:      &[]string{"aaa"},
  1607  					},
  1608  				},
  1609  			},
  1610  		},
  1611  		{
  1612  			name: "importmulti with scriptPubKey address",
  1613  			newCmd: func() (interface{}, error) {
  1614  				return btcjson.NewCmd(
  1615  					"importmulti",
  1616  					// Cannot use a native string, due to special types like timestamp and scriptPubKey
  1617  					[]btcjson.ImportMultiRequest{
  1618  						{
  1619  							ScriptPubKey:  &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}},
  1620  							WitnessScript: btcjson.String("123"),
  1621  							Timestamp:     btcjson.TimestampOrNow{Value: 0},
  1622  							Keys:          &[]string{"aaa"},
  1623  						},
  1624  					},
  1625  				)
  1626  			},
  1627  			staticCmd: func() interface{} {
  1628  				requests := []btcjson.ImportMultiRequest{
  1629  					{
  1630  						ScriptPubKey:  &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}},
  1631  						WitnessScript: btcjson.String("123"),
  1632  						Timestamp:     btcjson.TimestampOrNow{Value: 0},
  1633  						Keys:          &[]string{"aaa"},
  1634  					},
  1635  				}
  1636  				return btcjson.NewImportMultiCmd(requests, nil)
  1637  			},
  1638  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"scriptPubKey":{"address":"addr"},"timestamp":0,"witnessscript":"123","keys":["aaa"]}]],"id":1}`,
  1639  			unmarshalled: &btcjson.ImportMultiCmd{
  1640  				Requests: []btcjson.ImportMultiRequest{
  1641  					{
  1642  						ScriptPubKey:  &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}},
  1643  						WitnessScript: btcjson.String("123"),
  1644  						Timestamp:     btcjson.TimestampOrNow{Value: 0},
  1645  						Keys:          &[]string{"aaa"},
  1646  					},
  1647  				},
  1648  			},
  1649  		},
  1650  		{
  1651  			name: "importmulti with ranged (int) descriptor",
  1652  			newCmd: func() (interface{}, error) {
  1653  				return btcjson.NewCmd(
  1654  					"importmulti",
  1655  					// Cannot use a native string, due to special types like timestamp.
  1656  					[]btcjson.ImportMultiRequest{
  1657  						{
  1658  							Descriptor: btcjson.String("123"),
  1659  							Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1660  							Range:      &btcjson.DescriptorRange{Value: 7},
  1661  						},
  1662  					},
  1663  				)
  1664  			},
  1665  			staticCmd: func() interface{} {
  1666  				requests := []btcjson.ImportMultiRequest{
  1667  					{
  1668  						Descriptor: btcjson.String("123"),
  1669  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1670  						Range:      &btcjson.DescriptorRange{Value: 7},
  1671  					},
  1672  				}
  1673  				return btcjson.NewImportMultiCmd(requests, nil)
  1674  			},
  1675  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"range":7}]],"id":1}`,
  1676  			unmarshalled: &btcjson.ImportMultiCmd{
  1677  				Requests: []btcjson.ImportMultiRequest{
  1678  					{
  1679  						Descriptor: btcjson.String("123"),
  1680  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1681  						Range:      &btcjson.DescriptorRange{Value: 7},
  1682  					},
  1683  				},
  1684  			},
  1685  		},
  1686  		{
  1687  			name: "importmulti with ranged (slice) descriptor",
  1688  			newCmd: func() (interface{}, error) {
  1689  				return btcjson.NewCmd(
  1690  					"importmulti",
  1691  					// Cannot use a native string, due to special types like timestamp.
  1692  					[]btcjson.ImportMultiRequest{
  1693  						{
  1694  							Descriptor: btcjson.String("123"),
  1695  							Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1696  							Range:      &btcjson.DescriptorRange{Value: []int{1, 7}},
  1697  						},
  1698  					},
  1699  				)
  1700  			},
  1701  			staticCmd: func() interface{} {
  1702  				requests := []btcjson.ImportMultiRequest{
  1703  					{
  1704  						Descriptor: btcjson.String("123"),
  1705  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1706  						Range:      &btcjson.DescriptorRange{Value: []int{1, 7}},
  1707  					},
  1708  				}
  1709  				return btcjson.NewImportMultiCmd(requests, nil)
  1710  			},
  1711  			marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"range":[1,7]}]],"id":1}`,
  1712  			unmarshalled: &btcjson.ImportMultiCmd{
  1713  				Requests: []btcjson.ImportMultiRequest{
  1714  					{
  1715  						Descriptor: btcjson.String("123"),
  1716  						Timestamp:  btcjson.TimestampOrNow{Value: 0},
  1717  						Range:      &btcjson.DescriptorRange{Value: []int{1, 7}},
  1718  					},
  1719  				},
  1720  			},
  1721  		},
  1722  		{
  1723  			name: "walletcreatefundedpsbt",
  1724  			newCmd: func() (interface{}, error) {
  1725  				return btcjson.NewCmd(
  1726  					"walletcreatefundedpsbt",
  1727  					[]btcjson.PsbtInput{
  1728  						{
  1729  							Txid:     "1234",
  1730  							Vout:     0,
  1731  							Sequence: 0,
  1732  						},
  1733  					},
  1734  					[]btcjson.PsbtOutput{
  1735  						btcjson.NewPsbtOutput("1234", palcutil.Amount(1234)),
  1736  						btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}),
  1737  					},
  1738  					btcjson.Uint32(1),
  1739  					btcjson.WalletCreateFundedPsbtOpts{},
  1740  					btcjson.Bool(true),
  1741  				)
  1742  			},
  1743  			staticCmd: func() interface{} {
  1744  				return btcjson.NewWalletCreateFundedPsbtCmd(
  1745  					[]btcjson.PsbtInput{
  1746  						{
  1747  							Txid:     "1234",
  1748  							Vout:     0,
  1749  							Sequence: 0,
  1750  						},
  1751  					},
  1752  					[]btcjson.PsbtOutput{
  1753  						btcjson.NewPsbtOutput("1234", palcutil.Amount(1234)),
  1754  						btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}),
  1755  					},
  1756  					btcjson.Uint32(1),
  1757  					&btcjson.WalletCreateFundedPsbtOpts{},
  1758  					btcjson.Bool(true),
  1759  				)
  1760  			},
  1761  			marshalled: `{"jsonrpc":"1.0","method":"walletcreatefundedpsbt","params":[[{"txid":"1234","vout":0,"sequence":0}],[{"1234":0.00001234},{"data":"01020304"}],1,{},true],"id":1}`,
  1762  			unmarshalled: &btcjson.WalletCreateFundedPsbtCmd{
  1763  				Inputs: []btcjson.PsbtInput{
  1764  					{
  1765  						Txid:     "1234",
  1766  						Vout:     0,
  1767  						Sequence: 0,
  1768  					},
  1769  				},
  1770  				Outputs: []btcjson.PsbtOutput{
  1771  					btcjson.NewPsbtOutput("1234", palcutil.Amount(1234)),
  1772  					btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}),
  1773  				},
  1774  				Locktime:    btcjson.Uint32(1),
  1775  				Options:     &btcjson.WalletCreateFundedPsbtOpts{},
  1776  				Bip32Derivs: btcjson.Bool(true),
  1777  			},
  1778  		},
  1779  		{
  1780  			name: "walletprocesspsbt",
  1781  			newCmd: func() (interface{}, error) {
  1782  				return btcjson.NewCmd(
  1783  					"walletprocesspsbt", "1234", btcjson.Bool(true), btcjson.String("ALL"), btcjson.Bool(true))
  1784  			},
  1785  			staticCmd: func() interface{} {
  1786  				return btcjson.NewWalletProcessPsbtCmd(
  1787  					"1234", btcjson.Bool(true), btcjson.String("ALL"), btcjson.Bool(true))
  1788  			},
  1789  			marshalled: `{"jsonrpc":"1.0","method":"walletprocesspsbt","params":["1234",true,"ALL",true],"id":1}`,
  1790  			unmarshalled: &btcjson.WalletProcessPsbtCmd{
  1791  				Psbt:        "1234",
  1792  				Sign:        btcjson.Bool(true),
  1793  				SighashType: btcjson.String("ALL"),
  1794  				Bip32Derivs: btcjson.Bool(true),
  1795  			},
  1796  		},
  1797  	}
  1798  
  1799  	t.Logf("Running %d tests", len(tests))
  1800  	for i, test := range tests {
  1801  		// Marshal the command as created by the new static command
  1802  		// creation function.
  1803  		marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd())
  1804  		if err != nil {
  1805  			t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
  1806  				test.name, err)
  1807  			continue
  1808  		}
  1809  
  1810  		if !bytes.Equal(marshalled, []byte(test.marshalled)) {
  1811  			t.Errorf("Test #%d (%s) unexpected marshalled data - "+
  1812  				"got %s, want %s", i, test.name, marshalled,
  1813  				test.marshalled)
  1814  			continue
  1815  		}
  1816  
  1817  		// Ensure the command is created without error via the generic
  1818  		// new command creation function.
  1819  		cmd, err := test.newCmd()
  1820  		if err != nil {
  1821  			t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
  1822  				i, test.name, err)
  1823  		}
  1824  
  1825  		// Marshal the command as created by the generic new command
  1826  		// creation function.
  1827  		marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd)
  1828  		if err != nil {
  1829  			t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
  1830  				test.name, err)
  1831  			continue
  1832  		}
  1833  
  1834  		if !bytes.Equal(marshalled, []byte(test.marshalled)) {
  1835  			t.Errorf("Test #%d (%s) unexpected marshalled data - "+
  1836  				"got %s, want %s", i, test.name, marshalled,
  1837  				test.marshalled)
  1838  			continue
  1839  		}
  1840  
  1841  		var request btcjson.Request
  1842  		if err := json.Unmarshal(marshalled, &request); err != nil {
  1843  			t.Errorf("Test #%d (%s) unexpected error while "+
  1844  				"unmarshalling JSON-RPC request: %v", i,
  1845  				test.name, err)
  1846  			continue
  1847  		}
  1848  
  1849  		cmd, err = btcjson.UnmarshalCmd(&request)
  1850  		if err != nil {
  1851  			t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
  1852  				test.name, err)
  1853  			continue
  1854  		}
  1855  
  1856  		if !reflect.DeepEqual(cmd, test.unmarshalled) {
  1857  			t.Errorf("Test #%d (%s) unexpected unmarshalled command "+
  1858  				"- got %s, want %s", i, test.name,
  1859  				fmt.Sprintf("(%T) %+[1]v", cmd),
  1860  				fmt.Sprintf("(%T) %+[1]v\n", test.unmarshalled))
  1861  			continue
  1862  		}
  1863  	}
  1864  }