2018-03-02 15:24:09 +00:00
|
|
|
package wallet
|
|
|
|
|
|
|
|
import (
|
2019-11-06 10:15:47 +00:00
|
|
|
"encoding/json"
|
2021-03-22 18:13:29 +00:00
|
|
|
"path"
|
2021-11-17 11:14:22 +00:00
|
|
|
"path/filepath"
|
2018-03-02 15:24:09 +00:00
|
|
|
"testing"
|
2019-11-06 10:15:47 +00:00
|
|
|
|
2020-03-03 14:21:42 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
2021-04-23 14:32:48 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
2020-03-13 14:23:45 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2020-01-15 15:10:40 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2019-11-06 10:15:47 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
walletTemplate = "testWallet"
|
2018-03-02 15:24:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestNewWallet(t *testing.T) {
|
2019-11-06 10:15:47 +00:00
|
|
|
wallet := checkWalletConstructor(t)
|
|
|
|
require.NotNil(t, wallet)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewWalletFromFile_Negative_EmptyFile(t *testing.T) {
|
|
|
|
_ = checkWalletConstructor(t)
|
|
|
|
walletFromFile, err2 := NewWalletFromFile(walletTemplate)
|
|
|
|
require.Errorf(t, err2, "EOF")
|
|
|
|
require.Nil(t, walletFromFile)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewWalletFromFile_Negative_NoFile(t *testing.T) {
|
|
|
|
_, err := NewWalletFromFile(walletTemplate)
|
|
|
|
require.Errorf(t, err, "open testWallet: no such file or directory")
|
|
|
|
}
|
|
|
|
|
2022-09-01 12:28:35 +00:00
|
|
|
func TestCreateAccountAndClose(t *testing.T) {
|
2019-11-06 10:15:47 +00:00
|
|
|
wallet := checkWalletConstructor(t)
|
|
|
|
|
|
|
|
errAcc := wallet.CreateAccount("testName", "testPass")
|
|
|
|
require.NoError(t, errAcc)
|
|
|
|
accounts := wallet.Accounts
|
|
|
|
require.Len(t, accounts, 1)
|
2022-09-01 12:28:35 +00:00
|
|
|
require.True(t, wallet.Accounts[0].CanSign())
|
|
|
|
wallet.Close()
|
|
|
|
require.False(t, wallet.Accounts[0].CanSign())
|
2019-11-06 10:15:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddAccount(t *testing.T) {
|
|
|
|
wallet := checkWalletConstructor(t)
|
|
|
|
|
|
|
|
wallet.AddAccount(&Account{
|
|
|
|
privateKey: nil,
|
2020-03-13 13:11:49 +00:00
|
|
|
Address: "real",
|
2019-11-06 10:15:47 +00:00
|
|
|
EncryptedWIF: "",
|
|
|
|
Label: "",
|
|
|
|
Contract: nil,
|
|
|
|
Locked: false,
|
|
|
|
Default: false,
|
|
|
|
})
|
|
|
|
accounts := wallet.Accounts
|
|
|
|
require.Len(t, accounts, 1)
|
2020-03-13 13:11:49 +00:00
|
|
|
|
|
|
|
require.Error(t, wallet.RemoveAccount("abc"))
|
|
|
|
require.Len(t, wallet.Accounts, 1)
|
|
|
|
require.NoError(t, wallet.RemoveAccount("real"))
|
|
|
|
require.Len(t, wallet.Accounts, 0)
|
2019-11-06 10:15:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPath(t *testing.T) {
|
|
|
|
wallet := checkWalletConstructor(t)
|
|
|
|
|
|
|
|
path := wallet.Path()
|
|
|
|
require.NotEmpty(t, path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSave(t *testing.T) {
|
2021-08-25 19:17:37 +00:00
|
|
|
wallet := checkWalletConstructor(t)
|
|
|
|
|
2019-11-06 10:15:47 +00:00
|
|
|
wallet.AddAccount(&Account{
|
|
|
|
privateKey: nil,
|
|
|
|
Address: "",
|
|
|
|
EncryptedWIF: "",
|
|
|
|
Label: "",
|
|
|
|
Contract: nil,
|
|
|
|
Locked: false,
|
|
|
|
Default: false,
|
|
|
|
})
|
|
|
|
|
|
|
|
errForSave := wallet.Save()
|
|
|
|
require.NoError(t, errForSave)
|
|
|
|
|
|
|
|
openedWallet, err := NewWalletFromFile(wallet.path)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, wallet.Accounts, openedWallet.Accounts)
|
2020-02-20 09:55:03 +00:00
|
|
|
|
|
|
|
t.Run("change and rewrite", func(t *testing.T) {
|
|
|
|
err := openedWallet.CreateAccount("test", "pass")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
w2, err := NewWalletFromFile(openedWallet.path)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 2, len(w2.Accounts))
|
2021-06-04 11:27:22 +00:00
|
|
|
require.NoError(t, w2.Accounts[1].Decrypt("pass", w2.Scrypt))
|
2022-09-01 16:04:47 +00:00
|
|
|
_ = w2.Accounts[1].ScriptHash() // openedWallet has it for acc 1.
|
2020-02-20 09:55:03 +00:00
|
|
|
require.Equal(t, openedWallet.Accounts, w2.Accounts)
|
|
|
|
})
|
2019-11-06 10:15:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestJSONMarshallUnmarshal(t *testing.T) {
|
|
|
|
wallet := checkWalletConstructor(t)
|
|
|
|
|
|
|
|
bytes, err := wallet.JSON()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, bytes)
|
|
|
|
|
|
|
|
unmarshalledWallet := &Wallet{}
|
|
|
|
errUnmarshal := json.Unmarshal(bytes, unmarshalledWallet)
|
|
|
|
|
|
|
|
require.NoError(t, errUnmarshal)
|
|
|
|
require.Equal(t, wallet.Version, unmarshalledWallet.Version)
|
|
|
|
require.Equal(t, wallet.Accounts, unmarshalledWallet.Accounts)
|
|
|
|
require.Equal(t, wallet.Scrypt, unmarshalledWallet.Scrypt)
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkWalletConstructor(t *testing.T) *Wallet {
|
2021-08-25 19:17:37 +00:00
|
|
|
tmpDir := t.TempDir()
|
2021-11-17 11:14:22 +00:00
|
|
|
file := filepath.Join(tmpDir, walletTemplate)
|
2021-08-25 19:17:37 +00:00
|
|
|
wallet, err := NewWallet(file)
|
2019-11-06 10:15:47 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
return wallet
|
|
|
|
}
|
|
|
|
|
2020-03-13 14:23:45 +00:00
|
|
|
func TestWallet_AddToken(t *testing.T) {
|
|
|
|
w := checkWalletConstructor(t)
|
2021-04-23 14:32:48 +00:00
|
|
|
tok := NewToken(util.Uint160{1, 2, 3}, "Rubl", "RUB", 2, manifest.NEP17StandardName)
|
2020-03-13 14:23:45 +00:00
|
|
|
require.Equal(t, 0, len(w.Extra.Tokens))
|
|
|
|
w.AddToken(tok)
|
|
|
|
require.Equal(t, 1, len(w.Extra.Tokens))
|
|
|
|
require.Error(t, w.RemoveToken(util.Uint160{4, 5, 6}))
|
|
|
|
require.Equal(t, 1, len(w.Extra.Tokens))
|
|
|
|
require.NoError(t, w.RemoveToken(tok.Hash))
|
|
|
|
require.Equal(t, 0, len(w.Extra.Tokens))
|
|
|
|
}
|
|
|
|
|
2020-01-15 15:10:40 +00:00
|
|
|
func TestWallet_GetAccount(t *testing.T) {
|
|
|
|
wallet := checkWalletConstructor(t)
|
|
|
|
accounts := []*Account{
|
|
|
|
{
|
|
|
|
Contract: &Contract{
|
|
|
|
Script: []byte{0, 1, 2, 3},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Contract: &Contract{
|
|
|
|
Script: []byte{3, 2, 1, 0},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, acc := range accounts {
|
2020-11-18 20:10:48 +00:00
|
|
|
acc.Address = address.Uint160ToString(acc.Contract.ScriptHash())
|
2020-01-15 15:10:40 +00:00
|
|
|
wallet.AddAccount(acc)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, acc := range accounts {
|
|
|
|
h := acc.Contract.ScriptHash()
|
|
|
|
assert.Equal(t, acc, wallet.GetAccount(h), "can't get %d account", i)
|
|
|
|
}
|
|
|
|
}
|
2020-02-14 16:17:07 +00:00
|
|
|
|
|
|
|
func TestWalletGetChangeAddress(t *testing.T) {
|
|
|
|
w1, err := NewWalletFromFile("testdata/wallet1.json")
|
|
|
|
require.NoError(t, err)
|
|
|
|
sh := w1.GetChangeAddress()
|
|
|
|
// No default address, the first one is used.
|
2021-05-11 13:32:09 +00:00
|
|
|
require.Equal(t, "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn", address.Uint160ToString(sh))
|
2020-02-14 16:17:07 +00:00
|
|
|
w2, err := NewWalletFromFile("testdata/wallet2.json")
|
|
|
|
require.NoError(t, err)
|
|
|
|
sh = w2.GetChangeAddress()
|
|
|
|
// Default address.
|
2021-05-11 13:32:09 +00:00
|
|
|
require.Equal(t, "NMUedC8TSV2rE17wGguSvPk9XcmHSaT275", address.Uint160ToString(sh))
|
2020-02-14 16:17:07 +00:00
|
|
|
}
|
2021-03-22 18:13:29 +00:00
|
|
|
|
|
|
|
func TestWalletForExamples(t *testing.T) {
|
|
|
|
const (
|
|
|
|
examplesDir = "../../examples"
|
|
|
|
walletFile = "my_wallet.json"
|
|
|
|
walletPass = "qwerty"
|
|
|
|
accountLabel = "my_account"
|
|
|
|
)
|
|
|
|
w, err := NewWalletFromFile(path.Join(examplesDir, walletFile))
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(w.Accounts))
|
|
|
|
require.Equal(t, accountLabel, w.Accounts[0].Label)
|
2021-06-04 11:27:22 +00:00
|
|
|
require.NoError(t, w.Accounts[0].Decrypt(walletPass, w.Scrypt))
|
2021-03-22 18:13:29 +00:00
|
|
|
|
|
|
|
// we need to keep the owner of the example contracts the same as the wallet account
|
2021-05-11 13:32:09 +00:00
|
|
|
require.Equal(t, "NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB", w.Accounts[0].Address, "need to change `owner` in the example contracts")
|
2021-03-22 18:13:29 +00:00
|
|
|
}
|