forked from TrueCloudLab/neoneo-go
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes: Go: ``` { "jsonrpc" : "2.0", "result" : { "received" : [ { "blockindex" : 65, "txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945", "transfernotifyindex" : 0, "timestamp" : 1605535020126, "transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY", "amount" : "29999999", "assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc" } ], "address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt", "sent" : [] }, "id" : 1 } ``` C#: ``` { "id" : 1, "result" : { "address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt", "sent" : [], "received" : [ { "transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY", "timestamp" : 1605535020126, "txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945", "blockindex" : 65, "transfernotifyindex" : 0, "amount" : "2999999900000000", "assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc" } ] }, "jsonrpc" : "2.0" } ```
This commit is contained in:
parent
82e5adb970
commit
8e29a200c0
2 changed files with 29 additions and 81 deletions
|
@ -554,16 +554,15 @@ func (s *Server) getNEP5Balances(ps request.Params) (interface{}, *response.Erro
|
||||||
Balances: []result.NEP5Balance{},
|
Balances: []result.NEP5Balance{},
|
||||||
}
|
}
|
||||||
if as != nil {
|
if as != nil {
|
||||||
cache := make(map[int32]decimals)
|
cache := make(map[int32]util.Uint160)
|
||||||
for id, bal := range as.Trackers {
|
for id, bal := range as.Trackers {
|
||||||
dec, err := s.getDecimals(id, cache)
|
h, err := s.getHash(id, cache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
amount := amountToString(&bal.Balance, dec.Value)
|
|
||||||
bs.Balances = append(bs.Balances, result.NEP5Balance{
|
bs.Balances = append(bs.Balances, result.NEP5Balance{
|
||||||
Asset: dec.Hash,
|
Asset: h,
|
||||||
Amount: amount,
|
Amount: bal.Balance.String(),
|
||||||
LastUpdated: bal.LastUpdatedBlock,
|
LastUpdated: bal.LastUpdatedBlock,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -637,7 +636,7 @@ func (s *Server) getNEP5Transfers(ps request.Params) (interface{}, *response.Err
|
||||||
Received: []result.NEP5Transfer{},
|
Received: []result.NEP5Transfer{},
|
||||||
Sent: []result.NEP5Transfer{},
|
Sent: []result.NEP5Transfer{},
|
||||||
}
|
}
|
||||||
cache := make(map[int32]decimals)
|
cache := make(map[int32]util.Uint160)
|
||||||
var resCount, frameCount int
|
var resCount, frameCount int
|
||||||
err = s.chain.ForEachNEP5Transfer(u, func(tr *state.NEP5Transfer) (bool, error) {
|
err = s.chain.ForEachNEP5Transfer(u, func(tr *state.NEP5Transfer) (bool, error) {
|
||||||
// Iterating from newest to oldest, not yet reached required
|
// Iterating from newest to oldest, not yet reached required
|
||||||
|
@ -656,25 +655,25 @@ func (s *Server) getNEP5Transfers(ps request.Params) (interface{}, *response.Err
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
d, err := s.getDecimals(tr.Asset, cache)
|
h, err := s.getHash(tr.Asset, cache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer := result.NEP5Transfer{
|
transfer := result.NEP5Transfer{
|
||||||
Timestamp: tr.Timestamp,
|
Timestamp: tr.Timestamp,
|
||||||
Asset: d.Hash,
|
Asset: h,
|
||||||
Index: tr.Block,
|
Index: tr.Block,
|
||||||
TxHash: tr.Tx,
|
TxHash: tr.Tx,
|
||||||
}
|
}
|
||||||
if tr.Amount.Sign() > 0 { // token was received
|
if tr.Amount.Sign() > 0 { // token was received
|
||||||
transfer.Amount = amountToString(&tr.Amount, d.Value)
|
transfer.Amount = tr.Amount.String()
|
||||||
if !tr.From.Equals(util.Uint160{}) {
|
if !tr.From.Equals(util.Uint160{}) {
|
||||||
transfer.Address = address.Uint160ToString(tr.From)
|
transfer.Address = address.Uint160ToString(tr.From)
|
||||||
}
|
}
|
||||||
bs.Received = append(bs.Received, transfer)
|
bs.Received = append(bs.Received, transfer)
|
||||||
} else {
|
} else {
|
||||||
transfer.Amount = amountToString(new(big.Int).Neg(&tr.Amount), d.Value)
|
transfer.Amount = new(big.Int).Neg(&tr.Amount).String()
|
||||||
if !tr.To.Equals(util.Uint160{}) {
|
if !tr.To.Equals(util.Uint160{}) {
|
||||||
transfer.Address = address.Uint160ToString(tr.To)
|
transfer.Address = address.Uint160ToString(tr.To)
|
||||||
}
|
}
|
||||||
|
@ -694,68 +693,17 @@ func (s *Server) getNEP5Transfers(ps request.Params) (interface{}, *response.Err
|
||||||
return bs, nil
|
return bs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func amountToString(amount *big.Int, decimals int64) string {
|
// getHash returns the hash of the contract by its ID using cache.
|
||||||
if decimals == 0 {
|
func (s *Server) getHash(contractID int32, cache map[int32]util.Uint160) (util.Uint160, error) {
|
||||||
return amount.String()
|
|
||||||
}
|
|
||||||
pow := int64(math.Pow10(int(decimals)))
|
|
||||||
q, r := new(big.Int).DivMod(amount, big.NewInt(pow), new(big.Int))
|
|
||||||
if r.Sign() == 0 {
|
|
||||||
return q.String()
|
|
||||||
}
|
|
||||||
fs := fmt.Sprintf("%%d.%%0%dd", decimals)
|
|
||||||
return fmt.Sprintf(fs, q, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// decimals represents decimals value for the contract with the specified scripthash.
|
|
||||||
type decimals struct {
|
|
||||||
Hash util.Uint160
|
|
||||||
Value int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) getDecimals(contractID int32, cache map[int32]decimals) (decimals, error) {
|
|
||||||
if d, ok := cache[contractID]; ok {
|
if d, ok := cache[contractID]; ok {
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
h, err := s.chain.GetContractScriptHash(contractID)
|
h, err := s.chain.GetContractScriptHash(contractID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return decimals{}, err
|
return util.Uint160{}, err
|
||||||
}
|
}
|
||||||
script, err := request.CreateFunctionInvocationScript(h, request.Params{
|
cache[contractID] = h
|
||||||
{
|
return h, nil
|
||||||
Type: request.StringT,
|
|
||||||
Value: "decimals",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: request.ArrayT,
|
|
||||||
Value: []request.Param{},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return decimals{}, fmt.Errorf("can't create script: %w", err)
|
|
||||||
}
|
|
||||||
res := s.runScriptInVM(script, nil)
|
|
||||||
if res == nil {
|
|
||||||
return decimals{}, fmt.Errorf("execution error: no result")
|
|
||||||
}
|
|
||||||
if res.State != "HALT" {
|
|
||||||
return decimals{}, fmt.Errorf("execution error: bad VM state %s due to an error %s", res.State, res.FaultException)
|
|
||||||
}
|
|
||||||
if len(res.Stack) == 0 {
|
|
||||||
return decimals{}, fmt.Errorf("execution error: empty stack")
|
|
||||||
}
|
|
||||||
|
|
||||||
d := decimals{Hash: h}
|
|
||||||
bi, err := res.Stack[len(res.Stack)-1].TryInteger()
|
|
||||||
if err != nil {
|
|
||||||
return decimals{}, err
|
|
||||||
}
|
|
||||||
d.Value = bi.Int64()
|
|
||||||
if d.Value < 0 {
|
|
||||||
return d, errors.New("incorrect result: negative result")
|
|
||||||
}
|
|
||||||
cache[contractID] = d
|
|
||||||
return d, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) contractIDFromParam(param *request.Param) (int32, *response.Error) {
|
func (s *Server) contractIDFromParam(param *request.Param) (int32, *response.Error) {
|
||||||
|
|
|
@ -1246,7 +1246,7 @@ func checkNep5Balances(t *testing.T, e *executor, acc interface{}) {
|
||||||
Balances: []result.NEP5Balance{
|
Balances: []result.NEP5Balance{
|
||||||
{
|
{
|
||||||
Asset: rubles,
|
Asset: rubles,
|
||||||
Amount: "8.77",
|
Amount: "877",
|
||||||
LastUpdated: 6,
|
LastUpdated: 6,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1256,7 +1256,7 @@ func checkNep5Balances(t *testing.T, e *executor, acc interface{}) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Amount: "800.09641770",
|
Amount: "80009641770",
|
||||||
LastUpdated: 7,
|
LastUpdated: 7,
|
||||||
}},
|
}},
|
||||||
Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(),
|
Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(),
|
||||||
|
@ -1327,7 +1327,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockDeploy2.Timestamp,
|
Timestamp: blockDeploy2.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // burn
|
Address: "", // burn
|
||||||
Amount: amountToString(big.NewInt(txDeploy2.SystemFee+txDeploy2.NetworkFee), 8),
|
Amount: big.NewInt(txDeploy2.SystemFee + txDeploy2.NetworkFee).String(),
|
||||||
Index: 7,
|
Index: 7,
|
||||||
TxHash: blockDeploy2.Hash(),
|
TxHash: blockDeploy2.Hash(),
|
||||||
},
|
},
|
||||||
|
@ -1335,7 +1335,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockSendRubles.Timestamp,
|
Timestamp: blockSendRubles.Timestamp,
|
||||||
Asset: rublesHash,
|
Asset: rublesHash,
|
||||||
Address: testchain.PrivateKeyByID(1).Address(),
|
Address: testchain.PrivateKeyByID(1).Address(),
|
||||||
Amount: "1.23",
|
Amount: "123",
|
||||||
Index: 6,
|
Index: 6,
|
||||||
NotifyIndex: 0,
|
NotifyIndex: 0,
|
||||||
TxHash: txSendRubles.Hash(),
|
TxHash: txSendRubles.Hash(),
|
||||||
|
@ -1344,7 +1344,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockSendRubles.Timestamp,
|
Timestamp: blockSendRubles.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // burn
|
Address: "", // burn
|
||||||
Amount: amountToString(big.NewInt(txSendRubles.SystemFee+txSendRubles.NetworkFee), 8),
|
Amount: big.NewInt(txSendRubles.SystemFee + txSendRubles.NetworkFee).String(),
|
||||||
Index: 6,
|
Index: 6,
|
||||||
TxHash: blockSendRubles.Hash(),
|
TxHash: blockSendRubles.Hash(),
|
||||||
},
|
},
|
||||||
|
@ -1352,7 +1352,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockReceiveRubles.Timestamp,
|
Timestamp: blockReceiveRubles.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // burn
|
Address: "", // burn
|
||||||
Amount: amountToString(big.NewInt(txReceiveRubles.SystemFee+txReceiveRubles.NetworkFee), 8),
|
Amount: big.NewInt(txReceiveRubles.SystemFee + txReceiveRubles.NetworkFee).String(),
|
||||||
Index: 5,
|
Index: 5,
|
||||||
TxHash: blockReceiveRubles.Hash(),
|
TxHash: blockReceiveRubles.Hash(),
|
||||||
},
|
},
|
||||||
|
@ -1360,7 +1360,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockReceiveRubles.Timestamp,
|
Timestamp: blockReceiveRubles.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // burn
|
Address: "", // burn
|
||||||
Amount: amountToString(big.NewInt(txInitCall.SystemFee+txInitCall.NetworkFee), 8),
|
Amount: big.NewInt(txInitCall.SystemFee + txInitCall.NetworkFee).String(),
|
||||||
Index: 5,
|
Index: 5,
|
||||||
TxHash: blockReceiveRubles.Hash(),
|
TxHash: blockReceiveRubles.Hash(),
|
||||||
},
|
},
|
||||||
|
@ -1377,7 +1377,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockSendNEO.Timestamp,
|
Timestamp: blockSendNEO.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // burn
|
Address: "", // burn
|
||||||
Amount: amountToString(big.NewInt(txSendNEO.SystemFee+txSendNEO.NetworkFee), 8),
|
Amount: big.NewInt(txSendNEO.SystemFee + txSendNEO.NetworkFee).String(),
|
||||||
Index: 4,
|
Index: 4,
|
||||||
TxHash: blockSendNEO.Hash(),
|
TxHash: blockSendNEO.Hash(),
|
||||||
},
|
},
|
||||||
|
@ -1385,7 +1385,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockCtrInv1.Timestamp,
|
Timestamp: blockCtrInv1.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // burn has empty receiver
|
Address: "", // burn has empty receiver
|
||||||
Amount: amountToString(big.NewInt(txCtrInv1.SystemFee+txCtrInv1.NetworkFee), 8),
|
Amount: big.NewInt(txCtrInv1.SystemFee + txCtrInv1.NetworkFee).String(),
|
||||||
Index: 3,
|
Index: 3,
|
||||||
TxHash: blockCtrInv1.Hash(),
|
TxHash: blockCtrInv1.Hash(),
|
||||||
},
|
},
|
||||||
|
@ -1393,7 +1393,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockCtrDeploy.Timestamp,
|
Timestamp: blockCtrDeploy.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // burn has empty receiver
|
Address: "", // burn has empty receiver
|
||||||
Amount: amountToString(big.NewInt(txCtrDeploy.SystemFee+txCtrDeploy.NetworkFee), 8),
|
Amount: big.NewInt(txCtrDeploy.SystemFee + txCtrDeploy.NetworkFee).String(),
|
||||||
Index: 2,
|
Index: 2,
|
||||||
TxHash: blockCtrDeploy.Hash(),
|
TxHash: blockCtrDeploy.Hash(),
|
||||||
},
|
},
|
||||||
|
@ -1403,7 +1403,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockGASBounty.Timestamp,
|
Timestamp: blockGASBounty.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "",
|
Address: "",
|
||||||
Amount: "0.50000000",
|
Amount: "50000000",
|
||||||
Index: 6,
|
Index: 6,
|
||||||
NotifyIndex: 0,
|
NotifyIndex: 0,
|
||||||
TxHash: blockGASBounty.Hash(),
|
TxHash: blockGASBounty.Hash(),
|
||||||
|
@ -1412,7 +1412,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockReceiveRubles.Timestamp,
|
Timestamp: blockReceiveRubles.Timestamp,
|
||||||
Asset: rublesHash,
|
Asset: rublesHash,
|
||||||
Address: address.Uint160ToString(rublesHash),
|
Address: address.Uint160ToString(rublesHash),
|
||||||
Amount: "10",
|
Amount: "1000",
|
||||||
Index: 5,
|
Index: 5,
|
||||||
NotifyIndex: 0,
|
NotifyIndex: 0,
|
||||||
TxHash: txReceiveRubles.Hash(),
|
TxHash: txReceiveRubles.Hash(),
|
||||||
|
@ -1421,7 +1421,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockSendNEO.Timestamp,
|
Timestamp: blockSendNEO.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "", // Minted GAS.
|
Address: "", // Minted GAS.
|
||||||
Amount: "1.49998500",
|
Amount: "149998500",
|
||||||
Index: 4,
|
Index: 4,
|
||||||
NotifyIndex: 0,
|
NotifyIndex: 0,
|
||||||
TxHash: txSendNEO.Hash(),
|
TxHash: txSendNEO.Hash(),
|
||||||
|
@ -1430,7 +1430,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockReceiveGAS.Timestamp,
|
Timestamp: blockReceiveGAS.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: testchain.MultisigAddress(),
|
Address: testchain.MultisigAddress(),
|
||||||
Amount: "1000",
|
Amount: "100000000000",
|
||||||
Index: 1,
|
Index: 1,
|
||||||
NotifyIndex: 0,
|
NotifyIndex: 0,
|
||||||
TxHash: txReceiveGAS.Hash(),
|
TxHash: txReceiveGAS.Hash(),
|
||||||
|
@ -1448,7 +1448,7 @@ func checkNep5TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcv
|
||||||
Timestamp: blockGASBounty0.Timestamp,
|
Timestamp: blockGASBounty0.Timestamp,
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Address: "",
|
Address: "",
|
||||||
Amount: "0.50000000",
|
Amount: "50000000",
|
||||||
Index: 0,
|
Index: 0,
|
||||||
TxHash: blockGASBounty0.Hash(),
|
TxHash: blockGASBounty0.Hash(),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue