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