1518019be8
Some commands don't accept arguments, but users try giving them and don't notice a mistake. It's a bit more user-friendly to tell the user that there is something wrong with the way he tries to use the command.
613 lines
20 KiB
Go
613 lines
20 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"math/big"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
// nftOwnerAddr is the owner of NFT-ND HASHY token (../examples/nft-nd/nft.go).
|
|
nftOwnerAddr = "NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB"
|
|
nftOwnerWallet = "../examples/my_wallet.json"
|
|
nftOwnerPass = "qwerty"
|
|
)
|
|
|
|
func TestNEP11Import(t *testing.T) {
|
|
e := newExecutor(t, true)
|
|
|
|
tmpDir := t.TempDir()
|
|
walletPath := filepath.Join(tmpDir, "walletForImport.json")
|
|
|
|
// deploy NFT NeoNameService contract
|
|
nnsContractHash := deployNNSContract(t, e)
|
|
// deploy NFT-D NeoFS Object contract
|
|
nfsContractHash := deployNFSContract(t, e)
|
|
neoContractHash, err := e.Chain.GetNativeContractScriptHash(nativenames.Neo)
|
|
require.NoError(t, err)
|
|
e.Run(t, "neo-go", "wallet", "init", "--wallet", walletPath)
|
|
|
|
args := []string{
|
|
"neo-go", "wallet", "nep11", "import",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
"--wallet", walletPath,
|
|
}
|
|
// missing token hash
|
|
e.RunWithError(t, args...)
|
|
|
|
// excessive parameters
|
|
e.RunWithError(t, append(args, "--token", nnsContractHash.StringLE(), "something")...)
|
|
|
|
// good: non-divisible
|
|
e.Run(t, append(args, "--token", nnsContractHash.StringLE())...)
|
|
|
|
// good: divisible
|
|
e.Run(t, append(args, "--token", nfsContractHash.StringLE())...)
|
|
|
|
// already exists
|
|
e.RunWithError(t, append(args, "--token", nnsContractHash.StringLE())...)
|
|
|
|
// not a NEP-11 token
|
|
e.RunWithError(t, append(args, "--token", neoContractHash.StringLE())...)
|
|
|
|
checkInfo := func(t *testing.T, h util.Uint160, name string, symbol string, decimals int) {
|
|
e.checkNextLine(t, "^Name:\\s*"+name)
|
|
e.checkNextLine(t, "^Symbol:\\s*"+symbol)
|
|
e.checkNextLine(t, "^Hash:\\s*"+h.StringLE())
|
|
e.checkNextLine(t, "^Decimals:\\s*"+strconv.Itoa(decimals))
|
|
e.checkNextLine(t, "^Address:\\s*"+address.Uint160ToString(h))
|
|
e.checkNextLine(t, "^Standard:\\s*"+string(manifest.NEP11StandardName))
|
|
}
|
|
t.Run("Info", func(t *testing.T) {
|
|
t.Run("excessive parameters", func(t *testing.T) {
|
|
e.RunWithError(t, "neo-go", "wallet", "nep11", "info",
|
|
"--wallet", walletPath, "--token", nnsContractHash.StringLE(), "qwerty")
|
|
})
|
|
t.Run("WithToken", func(t *testing.T) {
|
|
e.Run(t, "neo-go", "wallet", "nep11", "info",
|
|
"--wallet", walletPath, "--token", nnsContractHash.StringLE())
|
|
checkInfo(t, nnsContractHash, "NameService", "NNS", 0)
|
|
})
|
|
t.Run("NoToken", func(t *testing.T) {
|
|
e.Run(t, "neo-go", "wallet", "nep11", "info",
|
|
"--wallet", walletPath)
|
|
checkInfo(t, nnsContractHash, "NameService", "NNS", 0)
|
|
e.checkNextLine(t, "")
|
|
checkInfo(t, nfsContractHash, "NeoFS Object NFT", "NFSO", 2)
|
|
})
|
|
})
|
|
|
|
t.Run("Remove", func(t *testing.T) {
|
|
e.RunWithError(t, "neo-go", "wallet", "nep11", "remove",
|
|
"--wallet", walletPath, "--token", nnsContractHash.StringLE(), "parameter")
|
|
e.In.WriteString("y\r")
|
|
e.Run(t, "neo-go", "wallet", "nep11", "remove",
|
|
"--wallet", walletPath, "--token", nnsContractHash.StringLE())
|
|
e.Run(t, "neo-go", "wallet", "nep11", "info",
|
|
"--wallet", walletPath)
|
|
checkInfo(t, nfsContractHash, "NeoFS Object NFT", "NFSO", 2)
|
|
_, err := e.Out.ReadString('\n')
|
|
require.Equal(t, err, io.EOF)
|
|
})
|
|
}
|
|
|
|
func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
|
|
e := newExecutor(t, true)
|
|
tmpDir := t.TempDir()
|
|
|
|
// copy wallet to temp dir in order not to overwrite the original file
|
|
bytesRead, err := os.ReadFile(nftOwnerWallet)
|
|
require.NoError(t, err)
|
|
wall := filepath.Join(tmpDir, "my_wallet.json")
|
|
err = os.WriteFile(wall, bytesRead, 0755)
|
|
require.NoError(t, err)
|
|
|
|
// transfer funds to contract owner
|
|
e.In.WriteString("one\r")
|
|
e.Run(t, "neo-go", "wallet", "nep17", "transfer",
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
|
"--wallet", validatorWallet,
|
|
"--to", nftOwnerAddr,
|
|
"--token", "GAS",
|
|
"--amount", "10000",
|
|
"--force",
|
|
"--from", validatorAddr)
|
|
e.checkTxPersisted(t)
|
|
|
|
// deploy NFT HASHY contract
|
|
h := deployNFTContract(t, e)
|
|
|
|
mint := func(t *testing.T) []byte {
|
|
// mint 1 HASHY token by transferring 10 GAS to HASHY contract
|
|
e.In.WriteString(nftOwnerPass + "\r")
|
|
e.Run(t, "neo-go", "wallet", "nep17", "transfer",
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--to", h.StringLE(),
|
|
"--token", "GAS",
|
|
"--amount", "10",
|
|
"--force",
|
|
"--from", nftOwnerAddr)
|
|
txMint, _ := e.checkTxPersisted(t)
|
|
|
|
// get NFT ID from AER
|
|
aer, err := e.Chain.GetAppExecResults(txMint.Hash(), trigger.Application)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(aer))
|
|
require.Equal(t, 2, len(aer[0].Events))
|
|
hashyMintEvent := aer[0].Events[1]
|
|
require.Equal(t, "Transfer", hashyMintEvent.Name)
|
|
tokenID, err := hashyMintEvent.Item.Value().([]stackitem.Item)[3].TryBytes()
|
|
require.NoError(t, err)
|
|
require.NotNil(t, tokenID)
|
|
return tokenID
|
|
}
|
|
|
|
tokenID := mint(t)
|
|
|
|
// check the balance
|
|
cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--address", nftOwnerAddr}
|
|
checkBalanceResult := func(t *testing.T, acc string, amount string) {
|
|
e.checkNextLine(t, "^\\s*Account\\s+"+acc)
|
|
e.checkNextLine(t, "^\\s*HASHY:\\s+HASHY NFT \\("+h.StringLE()+"\\)")
|
|
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+amount+"$")
|
|
e.checkEOF(t)
|
|
}
|
|
// balance check: by symbol, token is not imported
|
|
e.RunWithError(t, append(cmdCheckBalance, "--token", "HASHY")...)
|
|
// balance check: excessive parameters
|
|
e.RunWithError(t, append(cmdCheckBalance, "--token", h.StringLE(), "neo-go")...)
|
|
// balance check: by hash, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, nftOwnerAddr, "1")
|
|
|
|
// import token
|
|
e.Run(t, "neo-go", "wallet", "nep11", "import",
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--token", h.StringLE())
|
|
|
|
// balance check: by symbol, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", "HASHY")...)
|
|
checkBalanceResult(t, nftOwnerAddr, "1")
|
|
|
|
// balance check: all accounts
|
|
e.Run(t, "neo-go", "wallet", "nep11", "balance",
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--token", h.StringLE())
|
|
checkBalanceResult(t, nftOwnerAddr, "1")
|
|
|
|
// remove token from wallet
|
|
e.In.WriteString("y\r")
|
|
e.Run(t, "neo-go", "wallet", "nep11", "remove",
|
|
"--wallet", wall, "--token", h.StringLE())
|
|
|
|
// ownerOf: missing contract hash
|
|
cmdOwnerOf := []string{"neo-go", "wallet", "nep11", "ownerOf",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdOwnerOf...)
|
|
cmdOwnerOf = append(cmdOwnerOf, "--token", h.StringLE())
|
|
|
|
// ownerOf: missing token ID
|
|
e.RunWithError(t, cmdOwnerOf...)
|
|
cmdOwnerOf = append(cmdOwnerOf, "--id", hex.EncodeToString(tokenID))
|
|
|
|
// ownerOf: good
|
|
e.Run(t, cmdOwnerOf...)
|
|
e.checkNextLine(t, nftOwnerAddr)
|
|
|
|
// tokensOf: missing contract hash
|
|
cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdTokensOf...)
|
|
cmdTokensOf = append(cmdTokensOf, "--token", h.StringLE())
|
|
|
|
// tokensOf: missing owner address
|
|
e.RunWithError(t, cmdTokensOf...)
|
|
cmdTokensOf = append(cmdTokensOf, "--address", nftOwnerAddr)
|
|
|
|
// tokensOf: good
|
|
e.Run(t, cmdTokensOf...)
|
|
require.Equal(t, hex.EncodeToString(tokenID), e.getNextLine(t))
|
|
|
|
// properties: no contract
|
|
cmdProperties := []string{
|
|
"neo-go", "wallet", "nep11", "properties",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdProperties...)
|
|
cmdProperties = append(cmdProperties, "--token", h.StringLE())
|
|
|
|
// properties: no token ID
|
|
e.RunWithError(t, cmdProperties...)
|
|
cmdProperties = append(cmdProperties, "--id", hex.EncodeToString(tokenID))
|
|
|
|
// properties: ok
|
|
e.Run(t, cmdProperties...)
|
|
require.Equal(t, fmt.Sprintf(`{"name":"HASHY %s"}`, base64.StdEncoding.EncodeToString(tokenID)), e.getNextLine(t))
|
|
|
|
// tokensOf: good, several tokens
|
|
tokenID1 := mint(t)
|
|
e.Run(t, cmdTokensOf...)
|
|
fst, snd := tokenID, tokenID1
|
|
if bytes.Compare(tokenID, tokenID1) == 1 {
|
|
fst, snd = snd, fst
|
|
}
|
|
|
|
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t))
|
|
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t))
|
|
|
|
// tokens: missing contract hash
|
|
cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdTokens...)
|
|
cmdTokens = append(cmdTokens, "--token", h.StringLE())
|
|
|
|
// tokens: excessive parameters
|
|
e.RunWithError(t, append(cmdTokens, "additional")...)
|
|
// tokens: good, several tokens
|
|
e.Run(t, cmdTokens...)
|
|
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t))
|
|
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t))
|
|
|
|
// balance check: several tokens, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, nftOwnerAddr, "2")
|
|
|
|
cmdTransfer := []string{
|
|
"neo-go", "wallet", "nep11", "transfer",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--to", validatorAddr,
|
|
"--from", nftOwnerAddr,
|
|
"--force",
|
|
}
|
|
|
|
// transfer: unimported token with symbol id specified
|
|
e.In.WriteString(nftOwnerPass + "\r")
|
|
e.RunWithError(t, append(cmdTransfer,
|
|
"--token", "HASHY")...)
|
|
cmdTransfer = append(cmdTransfer, "--token", h.StringLE())
|
|
|
|
// transfer: no id specified
|
|
e.In.WriteString(nftOwnerPass + "\r")
|
|
e.RunWithError(t, cmdTransfer...)
|
|
|
|
// transfer: good
|
|
e.In.WriteString(nftOwnerPass + "\r")
|
|
e.Run(t, append(cmdTransfer, "--id", hex.EncodeToString(tokenID))...)
|
|
e.checkTxPersisted(t)
|
|
|
|
// check balance after transfer
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, nftOwnerAddr, "1") // tokenID1
|
|
|
|
// transfer: good, to NEP-11-Payable contract, with data
|
|
verifyH := deployVerifyContract(t, e)
|
|
cmdTransfer = []string{
|
|
"neo-go", "wallet", "nep11", "transfer",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--to", verifyH.StringLE(),
|
|
"--from", nftOwnerAddr,
|
|
"--token", h.StringLE(),
|
|
"--id", hex.EncodeToString(tokenID1),
|
|
"--force",
|
|
"string:some_data",
|
|
}
|
|
e.In.WriteString(nftOwnerPass + "\r")
|
|
e.Run(t, cmdTransfer...)
|
|
tx, _ := e.checkTxPersisted(t)
|
|
// check OnNEP11Payment event
|
|
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 2, len(aer[0].Events))
|
|
nftOwnerHash, err := address.StringToUint160(nftOwnerAddr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, state.NotificationEvent{
|
|
ScriptHash: verifyH,
|
|
Name: "OnNEP11Payment",
|
|
Item: stackitem.NewArray([]stackitem.Item{
|
|
stackitem.NewByteArray(nftOwnerHash.BytesBE()),
|
|
stackitem.NewBigInteger(big.NewInt(1)),
|
|
stackitem.NewByteArray(tokenID1),
|
|
stackitem.NewByteArray([]byte("some_data")),
|
|
}),
|
|
}, aer[0].Events[1])
|
|
|
|
// check balance after transfer
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, nftOwnerAddr, "0")
|
|
}
|
|
|
|
func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
|
|
e := newExecutor(t, true)
|
|
tmpDir := t.TempDir()
|
|
|
|
// copy wallet to temp dir in order not to overwrite the original file
|
|
bytesRead, err := os.ReadFile(validatorWallet)
|
|
require.NoError(t, err)
|
|
wall := filepath.Join(tmpDir, "my_wallet.json")
|
|
err = os.WriteFile(wall, bytesRead, 0755)
|
|
require.NoError(t, err)
|
|
|
|
// deploy NeoFS Object contract
|
|
h := deployNFSContract(t, e)
|
|
|
|
mint := func(t *testing.T, containerID, objectID util.Uint256) []byte {
|
|
// mint 1.00 NFSO token by transferring 10 GAS to NFSO contract
|
|
e.In.WriteString(validatorPass + "\r")
|
|
e.Run(t, "neo-go", "wallet", "nep17", "transfer",
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--to", h.StringLE(),
|
|
"--token", "GAS",
|
|
"--amount", "10",
|
|
"--force",
|
|
"--from", validatorAddr,
|
|
"--", "[", "hash256:"+containerID.StringLE(), "hash256:"+objectID.StringLE(), "]",
|
|
)
|
|
txMint, _ := e.checkTxPersisted(t)
|
|
|
|
// get NFT ID from AER
|
|
aer, err := e.Chain.GetAppExecResults(txMint.Hash(), trigger.Application)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(aer))
|
|
require.Equal(t, 2, len(aer[0].Events))
|
|
nfsoMintEvent := aer[0].Events[1]
|
|
require.Equal(t, "Transfer", nfsoMintEvent.Name)
|
|
tokenID, err := nfsoMintEvent.Item.Value().([]stackitem.Item)[3].TryBytes()
|
|
require.NoError(t, err)
|
|
require.NotNil(t, tokenID)
|
|
return tokenID
|
|
}
|
|
|
|
container1ID := util.Uint256{1, 2, 3}
|
|
object1ID := util.Uint256{4, 5, 6}
|
|
token1ID := mint(t, container1ID, object1ID)
|
|
|
|
container2ID := util.Uint256{7, 8, 9}
|
|
object2ID := util.Uint256{10, 11, 12}
|
|
token2ID := mint(t, container2ID, object2ID)
|
|
|
|
// check properties
|
|
e.Run(t, "neo-go", "wallet", "nep11", "properties",
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
|
"--token", h.StringLE(),
|
|
"--id", hex.EncodeToString(token1ID))
|
|
jProps := e.getNextLine(t)
|
|
props := make(map[string]string)
|
|
require.NoError(t, json.Unmarshal([]byte(jProps), &props))
|
|
require.Equal(t, base64.StdEncoding.EncodeToString(container1ID.BytesBE()), props["containerID"])
|
|
require.Equal(t, base64.StdEncoding.EncodeToString(object1ID.BytesBE()), props["objectID"])
|
|
e.checkEOF(t)
|
|
|
|
// check the balance
|
|
cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--address", validatorAddr}
|
|
checkBalanceResult := func(t *testing.T, acc string, amount string, id []byte) {
|
|
e.checkNextLine(t, "^\\s*Account\\s+"+acc)
|
|
if id == nil {
|
|
e.checkNextLine(t, "^\\s*NFSO:\\s+NeoFS Object NFT \\("+h.StringLE()+"\\)")
|
|
} else {
|
|
e.checkNextLine(t, "^\\s*NFSO:\\s+NeoFS Object NFT \\("+h.StringLE()+", "+hex.EncodeToString(id)+"\\)")
|
|
}
|
|
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+amount+"$")
|
|
e.checkEOF(t)
|
|
}
|
|
// balance check: by symbol, token is not imported
|
|
e.RunWithError(t, append(cmdCheckBalance, "--token", "NFSO")...)
|
|
|
|
// overall NFSO balance check: by hash, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, validatorAddr, "2", nil)
|
|
|
|
// particular NFSO balance check: by hash, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE(), "--id", hex.EncodeToString(token2ID))...)
|
|
checkBalanceResult(t, validatorAddr, "1", token2ID)
|
|
|
|
// import token
|
|
e.Run(t, "neo-go", "wallet", "nep11", "import",
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--token", h.StringLE())
|
|
|
|
// overall balance check: by symbol, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", "NFSO")...)
|
|
checkBalanceResult(t, validatorAddr, "2", nil)
|
|
|
|
// particular balance check: by symbol, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", "NFSO", "--id", hex.EncodeToString(token1ID))...)
|
|
checkBalanceResult(t, validatorAddr, "1", token1ID)
|
|
|
|
// remove token from wallet
|
|
e.In.WriteString("y\r")
|
|
e.Run(t, "neo-go", "wallet", "nep11", "remove",
|
|
"--wallet", wall, "--token", h.StringLE())
|
|
|
|
// ownerOfD: missing contract hash
|
|
cmdOwnerOf := []string{"neo-go", "wallet", "nep11", "ownerOfD",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdOwnerOf...)
|
|
cmdOwnerOf = append(cmdOwnerOf, "--token", h.StringLE())
|
|
|
|
// ownerOfD: missing token ID
|
|
e.RunWithError(t, cmdOwnerOf...)
|
|
cmdOwnerOf = append(cmdOwnerOf, "--id", hex.EncodeToString(token1ID))
|
|
|
|
// ownerOfD: good
|
|
e.Run(t, cmdOwnerOf...)
|
|
e.checkNextLine(t, validatorAddr)
|
|
|
|
// tokensOf: missing contract hash
|
|
cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdTokensOf...)
|
|
cmdTokensOf = append(cmdTokensOf, "--token", h.StringLE())
|
|
|
|
// tokensOf: missing owner address
|
|
e.RunWithError(t, cmdTokensOf...)
|
|
cmdTokensOf = append(cmdTokensOf, "--address", validatorAddr)
|
|
|
|
// tokensOf: good
|
|
e.Run(t, cmdTokensOf...)
|
|
require.Equal(t, hex.EncodeToString(token1ID), e.getNextLine(t))
|
|
require.Equal(t, hex.EncodeToString(token2ID), e.getNextLine(t))
|
|
e.checkEOF(t)
|
|
|
|
// properties: no contract
|
|
cmdProperties := []string{
|
|
"neo-go", "wallet", "nep11", "properties",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdProperties...)
|
|
cmdProperties = append(cmdProperties, "--token", h.StringLE())
|
|
|
|
// properties: no token ID
|
|
e.RunWithError(t, cmdProperties...)
|
|
cmdProperties = append(cmdProperties, "--id", hex.EncodeToString(token2ID))
|
|
|
|
// properties: additional parameter
|
|
e.RunWithError(t, append(cmdProperties, "additiona")...)
|
|
|
|
// properties: ok
|
|
e.Run(t, cmdProperties...)
|
|
jProps = e.getNextLine(t)
|
|
props = make(map[string]string)
|
|
require.NoError(t, json.Unmarshal([]byte(jProps), &props))
|
|
require.Equal(t, base64.StdEncoding.EncodeToString(container2ID.BytesBE()), props["containerID"])
|
|
require.Equal(t, base64.StdEncoding.EncodeToString(object2ID.BytesBE()), props["objectID"])
|
|
e.checkEOF(t)
|
|
|
|
// tokensOf: good, several tokens
|
|
e.Run(t, cmdTokensOf...)
|
|
fst, snd := token1ID, token2ID
|
|
if bytes.Compare(token1ID, token2ID) == 1 {
|
|
fst, snd = snd, fst
|
|
}
|
|
|
|
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t))
|
|
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t))
|
|
|
|
// tokens: missing contract hash
|
|
cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
}
|
|
e.RunWithError(t, cmdTokens...)
|
|
cmdTokens = append(cmdTokens, "--token", h.StringLE())
|
|
|
|
// tokens: good, several tokens
|
|
e.Run(t, cmdTokens...)
|
|
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t))
|
|
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t))
|
|
|
|
// balance check: several tokens, ok
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, validatorAddr, "2", nil)
|
|
|
|
cmdTransfer := []string{
|
|
"neo-go", "wallet", "nep11", "transfer",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--to", nftOwnerAddr,
|
|
"--from", validatorAddr,
|
|
"--force",
|
|
}
|
|
|
|
// transfer: unimported token with symbol id specified
|
|
e.In.WriteString(validatorPass + "\r")
|
|
e.RunWithError(t, append(cmdTransfer,
|
|
"--token", "NFSO")...)
|
|
cmdTransfer = append(cmdTransfer, "--token", h.StringLE())
|
|
|
|
// transfer: no id specified
|
|
e.In.WriteString(validatorPass + "\r")
|
|
e.RunWithError(t, cmdTransfer...)
|
|
|
|
// transfer: good
|
|
e.In.WriteString(validatorPass + "\r")
|
|
e.Run(t, append(cmdTransfer, "--id", hex.EncodeToString(token1ID))...)
|
|
e.checkTxPersisted(t)
|
|
|
|
// check balance after transfer
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, validatorAddr, "1", nil) // only token2ID expected to be on the balance
|
|
|
|
// transfer: good, 1/4 of the balance, to NEP-11-Payable contract, with data
|
|
verifyH := deployVerifyContract(t, e)
|
|
cmdTransfer = []string{
|
|
"neo-go", "wallet", "nep11", "transfer",
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
|
"--wallet", wall,
|
|
"--to", verifyH.StringLE(),
|
|
"--from", validatorAddr,
|
|
"--token", h.StringLE(),
|
|
"--id", hex.EncodeToString(token2ID),
|
|
"--amount", "0.25",
|
|
"--force",
|
|
"string:some_data",
|
|
}
|
|
e.In.WriteString(validatorPass + "\r")
|
|
e.Run(t, cmdTransfer...)
|
|
tx, _ := e.checkTxPersisted(t)
|
|
// check OnNEP11Payment event
|
|
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 2, len(aer[0].Events))
|
|
validatorHash, err := address.StringToUint160(validatorAddr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, state.NotificationEvent{
|
|
ScriptHash: verifyH,
|
|
Name: "OnNEP11Payment",
|
|
Item: stackitem.NewArray([]stackitem.Item{
|
|
stackitem.NewByteArray(validatorHash.BytesBE()),
|
|
stackitem.NewBigInteger(big.NewInt(25)),
|
|
stackitem.NewByteArray(token2ID),
|
|
stackitem.NewByteArray([]byte("some_data")),
|
|
}),
|
|
}, aer[0].Events[1])
|
|
|
|
// check balance after transfer
|
|
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
|
checkBalanceResult(t, validatorAddr, "0.75", nil)
|
|
}
|
|
|
|
func deployNFSContract(t *testing.T, e *executor) util.Uint160 {
|
|
return deployContract(t, e, "../examples/nft-d/nft.go", "../examples/nft-d/nft.yml", validatorWallet, validatorAddr, validatorPass)
|
|
}
|
|
|
|
func deployNFTContract(t *testing.T, e *executor) util.Uint160 {
|
|
return deployContract(t, e, "../examples/nft-nd/nft.go", "../examples/nft-nd/nft.yml", nftOwnerWallet, nftOwnerAddr, nftOwnerPass)
|
|
}
|
|
|
|
func deployNNSContract(t *testing.T, e *executor) util.Uint160 {
|
|
return deployContract(t, e, "../examples/nft-nd-nns/", "../examples/nft-nd-nns/nns.yml", validatorWallet, validatorAddr, validatorPass)
|
|
}
|