forked from TrueCloudLab/neoneo-go
Merge pull request #1572 from nspcc-dev/getunclaimed
Return FP strings for getunclaimedgas
This commit is contained in:
commit
d5006c60ee
19 changed files with 205 additions and 104 deletions
|
@ -4,13 +4,13 @@ import (
|
|||
"flag"
|
||||
"strings"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// Fixed8 is a wrapper for Uint160 with flag.Value methods.
|
||||
type Fixed8 struct {
|
||||
Value util.Fixed8
|
||||
Value fixedn.Fixed8
|
||||
}
|
||||
|
||||
// Fixed8Flag is a flag with type string.
|
||||
|
@ -32,7 +32,7 @@ func (a Fixed8) String() string {
|
|||
|
||||
// Set implements flag.Value interface.
|
||||
func (a *Fixed8) Set(s string) error {
|
||||
f, err := util.Fixed8FromString(s)
|
||||
f, err := fixedn.Fixed8FromString(s)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func (a *Fixed8) Set(s string) error {
|
|||
}
|
||||
|
||||
// Fixed8 casts address to util.Fixed8.
|
||||
func (a *Fixed8) Fixed8() util.Fixed8 {
|
||||
func (a *Fixed8) Fixed8() fixedn.Fixed8 {
|
||||
return a.Value
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,6 @@ func (f Fixed8Flag) Apply(set *flag.FlagSet) {
|
|||
}
|
||||
|
||||
// Fixed8FromContext returns parsed util.Fixed8 value provided flag name.
|
||||
func Fixed8FromContext(ctx *cli.Context, name string) util.Fixed8 {
|
||||
func Fixed8FromContext(ctx *cli.Context, name string) fixedn.Fixed8 {
|
||||
return ctx.Generic(name).(*Fixed8).Value
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ import (
|
|||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFixed8_String(t *testing.T) {
|
||||
value := util.Fixed8(123)
|
||||
value := fixedn.Fixed8(123)
|
||||
f := Fixed8{
|
||||
Value: value,
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ func TestFixed8_String(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFixed8_Set(t *testing.T) {
|
||||
value := util.Fixed8(123)
|
||||
value := fixedn.Fixed8(123)
|
||||
f := Fixed8{}
|
||||
|
||||
require.Error(t, f.Set("not-a-fixed8"))
|
||||
|
@ -30,10 +30,10 @@ func TestFixed8_Set(t *testing.T) {
|
|||
|
||||
func TestFixed8_Fixed8(t *testing.T) {
|
||||
f := Fixed8{
|
||||
Value: util.Fixed8(123),
|
||||
Value: fixedn.Fixed8(123),
|
||||
}
|
||||
|
||||
require.Equal(t, util.Fixed8(123), f.Fixed8())
|
||||
require.Equal(t, fixedn.Fixed8(123), f.Fixed8())
|
||||
}
|
||||
|
||||
func TestFixed8Flag_String(t *testing.T) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -47,7 +47,7 @@ func TestNEP17Balance(t *testing.T) {
|
|||
e.checkNextLine(t, "^\\s*Account\\s+"+validatorAddr)
|
||||
e.checkNextLine(t, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
|
||||
b := e.Chain.GetUtilityTokenBalance(validatorHash)
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+util.Fixed8(b.Int64()).String())
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(b.Int64()).String())
|
||||
})
|
||||
t.Run("all accounts", func(t *testing.T) {
|
||||
e.Run(t, cmdbase...)
|
||||
|
@ -56,7 +56,7 @@ func TestNEP17Balance(t *testing.T) {
|
|||
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr1))
|
||||
e.checkNextLine(t, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
|
||||
balance := e.Chain.GetUtilityTokenBalance(addr1)
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+util.Fixed8(balance.Int64()).String())
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String())
|
||||
e.checkNextLine(t, "^\\s*Updated:")
|
||||
e.checkNextLine(t, "^\\s*$")
|
||||
|
||||
|
@ -74,7 +74,7 @@ func TestNEP17Balance(t *testing.T) {
|
|||
if strings.Contains(line, "GAS") {
|
||||
e.checkLine(t, line, "^\\s*GAS:\\s+GAS \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
|
||||
balance = e.Chain.GetUtilityTokenBalance(addr3)
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+util.Fixed8(balance.Int64()).String())
|
||||
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String())
|
||||
e.checkNextLine(t, "^\\s*Updated:")
|
||||
} else {
|
||||
balance, index := e.Chain.GetGoverningTokenBalance(validatorHash)
|
||||
|
@ -156,7 +156,7 @@ func TestNEP17MultiTransfer(t *testing.T) {
|
|||
b, _ := e.Chain.GetGoverningTokenBalance(privs[0].GetScriptHash())
|
||||
require.Equal(t, big.NewInt(42), b)
|
||||
b = e.Chain.GetUtilityTokenBalance(privs[1].GetScriptHash())
|
||||
require.Equal(t, big.NewInt(int64(util.Fixed8FromInt64(7))), b)
|
||||
require.Equal(t, big.NewInt(int64(fixedn.Fixed8FromInt64(7))), b)
|
||||
b, _ = e.Chain.GetGoverningTokenBalance(privs[2].GetScriptHash())
|
||||
require.Equal(t, big.NewInt(13), b)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
|
@ -446,7 +447,7 @@ func invokeFunction(ctx *cli.Context) error {
|
|||
func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
||||
var (
|
||||
err error
|
||||
gas util.Fixed8
|
||||
gas fixedn.Fixed8
|
||||
operation string
|
||||
params = make([]smartcontract.Parameter, 0)
|
||||
paramsStart = 1
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/cli/paramcontext"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
|
@ -390,14 +391,14 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid address: '%s'", ss[1]), 1)
|
||||
}
|
||||
amount, err := util.FixedNFromString(ss[2], int(token.Decimals))
|
||||
amount, err := fixedn.FromString(ss[2], int(token.Decimals))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
|
||||
}
|
||||
recipients = append(recipients, client.TransferTarget{
|
||||
Token: token.Hash,
|
||||
Address: addr,
|
||||
Amount: amount,
|
||||
Amount: amount.Int64(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -437,7 +438,7 @@ func transferNEP17(ctx *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
amount, err := util.FixedNFromString(ctx.String("amount"), int(token.Decimals))
|
||||
amount, err := fixedn.FromString(ctx.String("amount"), int(token.Decimals))
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
|
||||
}
|
||||
|
@ -445,7 +446,7 @@ func transferNEP17(ctx *cli.Context) error {
|
|||
return signAndSendTransfer(ctx, c, acc, []client.TransferTarget{{
|
||||
Token: token.Hash,
|
||||
Address: to,
|
||||
Amount: amount,
|
||||
Amount: amount.Int64(),
|
||||
}})
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
|
@ -198,7 +199,7 @@ func TestCreateBasicChain(t *testing.T) {
|
|||
acc0 := wallet.NewAccountFromPrivateKey(priv0)
|
||||
|
||||
// Prepare some transaction for future submission.
|
||||
txSendRaw := newNEP17Transfer(bc.contracts.NEO.Hash, priv0ScriptHash, priv1.GetScriptHash(), int64(util.Fixed8FromInt64(1000)))
|
||||
txSendRaw := newNEP17Transfer(bc.contracts.NEO.Hash, priv0ScriptHash, priv1.GetScriptHash(), int64(fixedn.Fixed8FromInt64(1000)))
|
||||
txSendRaw.ValidUntilBlock = transaction.MaxValidUntilBlockIncrement
|
||||
txSendRaw.Nonce = 0x1234
|
||||
txSendRaw.Signers = []transaction.Signer{{
|
||||
|
@ -245,7 +246,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
|
|||
txMoveNeo, err := testchain.NewTransferFromOwner(bc, neoHash, priv0ScriptHash, neoAmount, getNextNonce(), validUntilBlock)
|
||||
require.NoError(t, err)
|
||||
// Move some GAS to one simple account.
|
||||
txMoveGas, err := testchain.NewTransferFromOwner(bc, gasHash, priv0ScriptHash, int64(util.Fixed8FromInt64(1000)),
|
||||
txMoveGas, err := testchain.NewTransferFromOwner(bc, gasHash, priv0ScriptHash, int64(fixedn.Fixed8FromInt64(1000)),
|
||||
getNextNonce(), validUntilBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -173,7 +174,7 @@ type Execution struct {
|
|||
type executionAux struct {
|
||||
Trigger string `json:"trigger"`
|
||||
VMState string `json:"vmstate"`
|
||||
GasConsumed util.Fixed8 `json:"gasconsumed,string"`
|
||||
GasConsumed fixedn.Fixed8 `json:"gasconsumed,string"`
|
||||
Stack json.RawMessage `json:"stack"`
|
||||
Events []NotificationEvent `json:"notifications"`
|
||||
FaultException string `json:"exception,omitempty"`
|
||||
|
@ -202,7 +203,7 @@ func (e Execution) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(&executionAux{
|
||||
Trigger: e.Trigger.String(),
|
||||
VMState: e.VMState.String(),
|
||||
GasConsumed: util.Fixed8(e.GasConsumed),
|
||||
GasConsumed: fixedn.Fixed8(e.GasConsumed),
|
||||
Stack: st,
|
||||
Events: e.Events,
|
||||
FaultException: e.FaultException,
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
@ -301,18 +302,18 @@ func (t *Transaction) Sender() util.Uint160 {
|
|||
// transactionJSON is a wrapper for Transaction and
|
||||
// used for correct marhalling of transaction.Data
|
||||
type transactionJSON struct {
|
||||
TxID util.Uint256 `json:"hash"`
|
||||
Size int `json:"size"`
|
||||
Version uint8 `json:"version"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
Sender string `json:"sender"`
|
||||
SystemFee util.Fixed8 `json:"sysfee,string"`
|
||||
NetworkFee util.Fixed8 `json:"netfee,string"`
|
||||
ValidUntilBlock uint32 `json:"validuntilblock"`
|
||||
Attributes []Attribute `json:"attributes"`
|
||||
Signers []Signer `json:"signers"`
|
||||
Script []byte `json:"script"`
|
||||
Scripts []Witness `json:"witnesses"`
|
||||
TxID util.Uint256 `json:"hash"`
|
||||
Size int `json:"size"`
|
||||
Version uint8 `json:"version"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
Sender string `json:"sender"`
|
||||
SystemFee fixedn.Fixed8 `json:"sysfee,string"`
|
||||
NetworkFee fixedn.Fixed8 `json:"netfee,string"`
|
||||
ValidUntilBlock uint32 `json:"validuntilblock"`
|
||||
Attributes []Attribute `json:"attributes"`
|
||||
Signers []Signer `json:"signers"`
|
||||
Script []byte `json:"script"`
|
||||
Scripts []Witness `json:"witnesses"`
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler interface.
|
||||
|
@ -328,8 +329,8 @@ func (t *Transaction) MarshalJSON() ([]byte, error) {
|
|||
Signers: t.Signers,
|
||||
Script: t.Script,
|
||||
Scripts: t.Scripts,
|
||||
SystemFee: util.Fixed8(t.SystemFee),
|
||||
NetworkFee: util.Fixed8(t.NetworkFee),
|
||||
SystemFee: fixedn.Fixed8(t.SystemFee),
|
||||
NetworkFee: fixedn.Fixed8(t.NetworkFee),
|
||||
}
|
||||
return json.Marshal(tx)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -119,8 +120,8 @@ func TestMarshalUnmarshalJSONInvocationTX(t *testing.T) {
|
|||
Script: []byte{1, 2, 3, 4},
|
||||
Attributes: []Attribute{{Type: HighPriority}},
|
||||
Scripts: []Witness{},
|
||||
SystemFee: int64(util.Fixed8FromFloat(123.45)),
|
||||
NetworkFee: int64(util.Fixed8FromFloat(0.123)),
|
||||
SystemFee: int64(fixedn.Fixed8FromFloat(123.45)),
|
||||
NetworkFee: int64(fixedn.Fixed8FromFloat(0.123)),
|
||||
Trimmed: false,
|
||||
}
|
||||
|
||||
|
|
80
pkg/encoding/fixedn/decimal.go
Normal file
80
pkg/encoding/fixedn/decimal.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
package fixedn
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const maxAllowedPrecision = 16
|
||||
|
||||
// ErrInvalidFormat is returned when decimal format is invalid.
|
||||
var ErrInvalidFormat = errors.New("invalid decimal format")
|
||||
|
||||
var _pow10 []*big.Int
|
||||
|
||||
func init() {
|
||||
var p = int64(1)
|
||||
for i := 0; i <= maxAllowedPrecision; i++ {
|
||||
_pow10 = append(_pow10, big.NewInt(p))
|
||||
p *= 10
|
||||
}
|
||||
}
|
||||
|
||||
func pow10(n int) *big.Int {
|
||||
last := len(_pow10) - 1
|
||||
if n <= last {
|
||||
return _pow10[n]
|
||||
}
|
||||
p := new(big.Int)
|
||||
p.Mul(_pow10[last], _pow10[1])
|
||||
for i := last + 1; i < n; i++ {
|
||||
p.Mul(p, _pow10[1])
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// ToString converts big decimal with specified precision to string.
|
||||
func ToString(bi *big.Int, precision int) string {
|
||||
var dp, fp big.Int
|
||||
dp.QuoRem(bi, pow10(precision), &fp)
|
||||
|
||||
var s = dp.String()
|
||||
if fp.Sign() == 0 {
|
||||
return s
|
||||
}
|
||||
frac := fp.Uint64()
|
||||
trimmed := 0
|
||||
for ; frac%10 == 0; frac /= 10 {
|
||||
trimmed++
|
||||
}
|
||||
return s + "." + fmt.Sprintf("%0"+strconv.FormatUint(uint64(precision-trimmed), 10)+"d", frac)
|
||||
}
|
||||
|
||||
// FromString converts string to a big decimal with specified precision.
|
||||
func FromString(s string, precision int) (*big.Int, error) {
|
||||
parts := strings.SplitN(s, ".", 2)
|
||||
bi, ok := new(big.Int).SetString(parts[0], 10)
|
||||
if !ok {
|
||||
return nil, ErrInvalidFormat
|
||||
}
|
||||
bi.Mul(bi, pow10(precision))
|
||||
if len(parts) == 1 {
|
||||
return bi, nil
|
||||
}
|
||||
|
||||
if len(parts[1]) > precision {
|
||||
return nil, ErrInvalidFormat
|
||||
}
|
||||
fp, ok := new(big.Int).SetString(parts[1], 10)
|
||||
if !ok {
|
||||
return nil, ErrInvalidFormat
|
||||
}
|
||||
fp.Mul(fp, pow10(precision-len(parts[1])))
|
||||
if bi.Sign() == -1 {
|
||||
return bi.Sub(bi, fp), nil
|
||||
}
|
||||
return bi.Add(bi, fp), nil
|
||||
}
|
51
pkg/encoding/fixedn/decimal_test.go
Normal file
51
pkg/encoding/fixedn/decimal_test.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package fixedn
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDecimalFromStringGood(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
bi *big.Int
|
||||
prec int
|
||||
s string
|
||||
}{
|
||||
{big.NewInt(123), 2, "1.23"},
|
||||
{big.NewInt(12300), 2, "123"},
|
||||
{big.NewInt(1234500000), 8, "12.345"},
|
||||
{big.NewInt(-12345), 3, "-12.345"},
|
||||
{big.NewInt(35), 8, "0.00000035"},
|
||||
{big.NewInt(1230), 5, "0.0123"},
|
||||
{big.NewInt(123456789), 20, "0.00000000000123456789"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.s, func(t *testing.T) {
|
||||
s := ToString(tc.bi, tc.prec)
|
||||
require.Equal(t, tc.s, s)
|
||||
|
||||
bi, err := FromString(s, tc.prec)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.bi, bi)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecimalFromStringBad(t *testing.T) {
|
||||
var errCases = []struct {
|
||||
s string
|
||||
prec int
|
||||
}{
|
||||
{"12A", 1},
|
||||
{"12.345", 2},
|
||||
{"12.3A", 2},
|
||||
}
|
||||
for _, tc := range errCases {
|
||||
t.Run(tc.s, func(t *testing.T) {
|
||||
_, err := FromString(tc.s, tc.prec)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
package util
|
||||
package fixedn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -72,36 +71,11 @@ func Fixed8FromFloat(val float64) Fixed8 {
|
|||
// Fixed8FromString parses s which must be a fixed point number
|
||||
// with precision up to 10^-8
|
||||
func Fixed8FromString(s string) (Fixed8, error) {
|
||||
num, err := FixedNFromString(s, precision)
|
||||
num, err := FromString(s, precision)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return Fixed8(num), err
|
||||
}
|
||||
|
||||
// FixedNFromString parses s which must be a fixed point number
|
||||
// with precision 10^-d.
|
||||
func FixedNFromString(s string, precision int) (int64, error) {
|
||||
parts := strings.SplitN(s, ".", 2)
|
||||
d := int64(math.Pow10(precision))
|
||||
ip, err := strconv.ParseInt(parts[0], 10, 64)
|
||||
if err != nil {
|
||||
return 0, errInvalidString
|
||||
} else if len(parts) == 1 {
|
||||
return ip * d, nil
|
||||
}
|
||||
|
||||
fp, err := strconv.ParseInt(parts[1], 10, 64)
|
||||
if err != nil || fp >= d {
|
||||
return 0, errInvalidString
|
||||
}
|
||||
for i := len(parts[1]); i < precision; i++ {
|
||||
fp *= 10
|
||||
}
|
||||
if ip < 0 {
|
||||
return ip*d - fp, nil
|
||||
}
|
||||
return ip*d + fp, nil
|
||||
return Fixed8(num.Int64()), err
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json unmarshaller interface.
|
|
@ -1,4 +1,4 @@
|
|||
package util
|
||||
package fixedn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
|
@ -85,20 +84,6 @@ func TestFixed8FromString(t *testing.T) {
|
|||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestFixedNFromString(t *testing.T) {
|
||||
val := "123.456"
|
||||
num, err := FixedNFromString(val, 3)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 123456, num)
|
||||
|
||||
num, err = FixedNFromString(val, 4)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 1234560, num)
|
||||
|
||||
_, err = FixedNFromString(val, 2)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestSatoshi(t *testing.T) {
|
||||
satoshif8 := Satoshi()
|
||||
assert.Equal(t, "0.00000001", satoshif8.String())
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||
|
@ -170,10 +171,10 @@ func (c *Client) GetBlockHeaderVerbose(hash util.Uint256) (*result.Header, error
|
|||
}
|
||||
|
||||
// GetBlockSysFee returns the system fees of the block, based on the specified index.
|
||||
func (c *Client) GetBlockSysFee(index uint32) (util.Fixed8, error) {
|
||||
func (c *Client) GetBlockSysFee(index uint32) (fixedn.Fixed8, error) {
|
||||
var (
|
||||
params = request.NewRawParams(index)
|
||||
resp util.Fixed8
|
||||
resp fixedn.Fixed8
|
||||
)
|
||||
if err := c.performRequest("getblocksysfee", params, &resp); err != nil {
|
||||
return resp, err
|
||||
|
@ -473,7 +474,7 @@ func (c *Client) SubmitBlock(b block.Block) (util.Uint256, error) {
|
|||
// SignAndPushInvocationTx signs and pushes given script as an invocation
|
||||
// transaction using given wif to sign it and spending the amount of gas
|
||||
// specified. It returns a hash of the invocation transaction and an error.
|
||||
func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sysfee int64, netfee util.Fixed8, cosigners []transaction.Signer) (util.Uint256, error) {
|
||||
func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sysfee int64, netfee fixedn.Fixed8, cosigners []transaction.Signer) (util.Uint256, error) {
|
||||
var txHash util.Uint256
|
||||
var err error
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
|
@ -285,7 +286,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
},
|
||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":"195500"}`,
|
||||
result: func(c *Client) interface{} {
|
||||
return util.Fixed8FromInt64(195500)
|
||||
return fixedn.Fixed8FromInt64(195500)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -642,7 +643,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
invoke: func(c *Client) (interface{}, error) {
|
||||
return c.GetUnclaimedGas("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB")
|
||||
},
|
||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB","unclaimed":"897299680935"}}`,
|
||||
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB","unclaimed":"8972.99680935"}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
addr, err := address.StringToUint160("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
|
@ -26,7 +26,7 @@ type Invoke struct {
|
|||
|
||||
type invokeAux struct {
|
||||
State string `json:"state"`
|
||||
GasConsumed util.Fixed8 `json:"gasconsumed,string"`
|
||||
GasConsumed fixedn.Fixed8 `json:"gasconsumed,string"`
|
||||
Script []byte `json:"script"`
|
||||
Stack json.RawMessage `json:"stack"`
|
||||
FaultException string `json:"exception,omitempty"`
|
||||
|
@ -55,7 +55,7 @@ func (r Invoke) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
return json.Marshal(&invokeAux{
|
||||
GasConsumed: util.Fixed8(r.GasConsumed),
|
||||
GasConsumed: fixedn.Fixed8(r.GasConsumed),
|
||||
Script: r.Script,
|
||||
State: r.State,
|
||||
Stack: st,
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -14,7 +14,7 @@ import (
|
|||
func TestInvoke_MarshalJSON(t *testing.T) {
|
||||
result := &Invoke{
|
||||
State: "HALT",
|
||||
GasConsumed: int64(util.Fixed8FromFloat(123.45)),
|
||||
GasConsumed: int64(fixedn.Fixed8FromFloat(123.45)),
|
||||
Script: []byte{10},
|
||||
Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))},
|
||||
FaultException: "",
|
||||
|
|
|
@ -2,10 +2,11 @@ package result
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -25,7 +26,7 @@ type unclaimedGas struct {
|
|||
func (g UnclaimedGas) MarshalJSON() ([]byte, error) {
|
||||
gas := &unclaimedGas{
|
||||
Address: address.Uint160ToString(g.Address),
|
||||
Unclaimed: g.Unclaimed.String(),
|
||||
Unclaimed: fixedn.ToString(&g.Unclaimed, 8),
|
||||
}
|
||||
return json.Marshal(gas)
|
||||
}
|
||||
|
@ -36,9 +37,9 @@ func (g *UnclaimedGas) UnmarshalJSON(data []byte) error {
|
|||
if err := json.Unmarshal(data, gas); err != nil {
|
||||
return err
|
||||
}
|
||||
uncl, ok := new(big.Int).SetString(gas.Unclaimed, 10)
|
||||
if !ok {
|
||||
return errors.New("failed to convert unclaimed gas")
|
||||
uncl, err := fixedn.FromString(gas.Unclaimed, 8)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert unclaimed gas: %w", err)
|
||||
}
|
||||
g.Unclaimed = *uncl
|
||||
addr, err := address.StringToUint160(gas.Address)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package rpc
|
||||
|
||||
import "github.com/nspcc-dev/neo-go/pkg/util"
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
)
|
||||
|
||||
type (
|
||||
// Config is an RPC service configuration information
|
||||
|
@ -10,9 +12,9 @@ type (
|
|||
EnableCORSWorkaround bool `yaml:"EnableCORSWorkaround"`
|
||||
// MaxGasInvoke is a maximum amount of gas which
|
||||
// can be spent during RPC call.
|
||||
MaxGasInvoke util.Fixed8 `yaml:"MaxGasInvoke"`
|
||||
Port uint16 `yaml:"Port"`
|
||||
TLSConfig TLSConfig `yaml:"TLSConfig"`
|
||||
MaxGasInvoke fixedn.Fixed8 `yaml:"MaxGasInvoke"`
|
||||
Port uint16 `yaml:"Port"`
|
||||
TLSConfig TLSConfig `yaml:"TLSConfig"`
|
||||
}
|
||||
|
||||
// TLSConfig describes SSL/TLS configuration.
|
||||
|
|
Loading…
Reference in a new issue