Skip to content

Commit

Permalink
Merge pull request #52 from ElrondNetwork/construction-cross
Browse files Browse the repository at this point in the history
Workaround (quick fix) to support construction of cross-shard transactions
  • Loading branch information
andreibancioiu authored Oct 5, 2022
2 parents f6cb340 + 8a8b10d commit 6e6122e
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 11 deletions.
38 changes: 27 additions & 11 deletions server/services/constructionService.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/ElrondNetwork/elrond-proxy-go/data"
"github.com/coinbase/rosetta-sdk-go/server"
Expand Down Expand Up @@ -38,9 +39,9 @@ func (service *constructionService) ConstructionPreprocess(
return nil, err
}

options, err := service.getOptionsFromOperations(request.Operations)
if err != nil {
return nil, err
options, errOptions := service.prepareConstructionOptions(request.Operations, request.Metadata)
if errOptions != nil {
return nil, service.errFactory.newErrWithOriginal(ErrConstructionCheck, errOptions)
}

if len(request.MaxFee) > 0 {
Expand Down Expand Up @@ -118,15 +119,30 @@ func checkOperationsType(op *types.Operation) bool {
return false
}

func (service *constructionService) getOptionsFromOperations(ops []*types.Operation) (objectsMap, *types.Error) {
if len(ops) < 2 {
return nil, service.errFactory.newErrWithOriginal(ErrConstructionCheck, errors.New("invalid number of operations"))
}
func (service *constructionService) prepareConstructionOptions(operations []*types.Operation, metadata objectsMap) (objectsMap, error) {
options := make(objectsMap)
options["sender"] = ops[0].Account.Address
options["receiver"] = ops[1].Account.Address
options["type"] = ops[0].Type
options["value"] = ops[1].Amount.Value
options["type"] = operations[0].Type
options["sender"] = operations[0].Account.Address

if metadata["receiver"] != nil {
options["receiver"] = metadata["receiver"]
} else {
if len(operations) > 1 {
options["receiver"] = operations[1].Account.Address
} else {
return nil, errors.New("cannot prepare transaction receiver")
}
}

if metadata["value"] != nil {
options["value"] = metadata["value"]
} else {
if len(operations) > 1 {
options["value"] = operations[1].Amount.Value
} else {
options["value"] = strings.Trim(operations[0].Amount.Value, "-")
}
}

return options, nil
}
Expand Down
102 changes: 102 additions & 0 deletions server/services/constructionService_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,105 @@ func TestConstructionService_CreateOperationsFromPreparedTx(t *testing.T) {
operations := service.createOperationsFromPreparedTx(preparedTx)
require.Equal(t, expectedOperations, operations)
}

func TestConstructionService_PrepareConstructionOptions(t *testing.T) {
t.Parallel()

networkProvider := testscommon.NewNetworkProviderMock()
extension := newNetworkProviderExtension(networkProvider)
service := NewConstructionService(networkProvider).(*constructionService)

t.Run("two operations, no metadata", func(t *testing.T) {
t.Parallel()

operations := []*types.Operation{
{
OperationIdentifier: indexToOperationIdentifier(0),
Type: opTransfer,
Account: addressToAccountIdentifier(testscommon.TestAddressAlice),
Amount: extension.valueToNativeAmount("-12345"),
},
{
OperationIdentifier: indexToOperationIdentifier(1),
Type: opTransfer,
Account: addressToAccountIdentifier(testscommon.TestAddressBob),
Amount: extension.valueToNativeAmount("12345"),
},
}

metadata := make(objectsMap)

options, err := service.prepareConstructionOptions(operations, metadata)
require.Nil(t, err)
require.Equal(t, opTransfer, options["type"])
require.Equal(t, testscommon.TestAddressAlice, options["sender"])
require.Equal(t, testscommon.TestAddressBob, options["receiver"])
require.Equal(t, "12345", options["value"])
})

t.Run("one operation, with metadata having: receiver", func(t *testing.T) {
t.Parallel()

operations := []*types.Operation{
{
OperationIdentifier: indexToOperationIdentifier(0),
Type: opTransfer,
Account: addressToAccountIdentifier(testscommon.TestAddressAlice),
Amount: extension.valueToNativeAmount("-12345"),
},
}

metadata := make(objectsMap)
metadata["receiver"] = testscommon.TestAddressBob

options, err := service.prepareConstructionOptions(operations, metadata)
require.Nil(t, err)
require.Equal(t, opTransfer, options["type"])
require.Equal(t, testscommon.TestAddressAlice, options["sender"])
require.Equal(t, testscommon.TestAddressBob, options["receiver"])
require.Equal(t, "12345", options["value"])
})

t.Run("one operation, with metadata having: receiver, value", func(t *testing.T) {
t.Parallel()

operations := []*types.Operation{
{
OperationIdentifier: indexToOperationIdentifier(0),
Type: opTransfer,
Account: addressToAccountIdentifier(testscommon.TestAddressAlice),
Amount: extension.valueToNativeAmount("ignored"),
},
}

metadata := make(objectsMap)
metadata["receiver"] = testscommon.TestAddressBob
metadata["value"] = "12345"

options, err := service.prepareConstructionOptions(operations, metadata)
require.Nil(t, err)
require.Equal(t, opTransfer, options["type"])
require.Equal(t, testscommon.TestAddressAlice, options["sender"])
require.Equal(t, testscommon.TestAddressBob, options["receiver"])
require.Equal(t, "12345", options["value"])
})

t.Run("one operation, with missing metadata: receiver", func(t *testing.T) {
t.Parallel()

operations := []*types.Operation{
{
OperationIdentifier: indexToOperationIdentifier(0),
Type: opTransfer,
Account: addressToAccountIdentifier(testscommon.TestAddressAlice),
Amount: extension.valueToNativeAmount("ignored"),
},
}

metadata := make(objectsMap)

options, err := service.prepareConstructionOptions(operations, metadata)
require.ErrorContains(t, err, "cannot prepare transaction receiver")
require.Nil(t, options)
})
}

0 comments on commit 6e6122e

Please sign in to comment.