feat(rostta): handle undelegation paypout transactions

pull/3649/head
xiaohuo 4 years ago committed by Leo Chen
parent 37aab8dee8
commit 2397fae0d7
  1. 13
      hmy/staking.go
  2. 71
      rosetta/services/tx_operation.go

@ -519,7 +519,9 @@ func (hmy *Harmony) GetDelegationsByDelegatorByBlock(
} }
// UndelegationPayouts .. // UndelegationPayouts ..
type UndelegationPayouts map[common.Address]*big.Int // delegator address => validator address => amount
type UndelegationPayouts map[common.Address]map[common.Address]*big.Int
// GetUndelegationPayouts returns the undelegation payouts for each delegator // GetUndelegationPayouts returns the undelegation payouts for each delegator
// //
@ -556,10 +558,13 @@ func (hmy *Harmony) GetUndelegationPayouts(
for _, delegation := range wrapper.Delegations { for _, delegation := range wrapper.Delegations {
withdraw := delegation.RemoveUnlockedUndelegations(epoch, wrapper.LastEpochInCommittee, lockingPeriod, noEarlyUnlock) withdraw := delegation.RemoveUnlockedUndelegations(epoch, wrapper.LastEpochInCommittee, lockingPeriod, noEarlyUnlock)
if withdraw.Cmp(bigZero) == 1 { if withdraw.Cmp(bigZero) == 1 {
if totalPayout, ok := undelegationPayouts[delegation.DelegatorAddress]; ok { if undelegationPayouts[delegation.DelegatorAddress] == nil {
undelegationPayouts[delegation.DelegatorAddress] = new(big.Int).Add(totalPayout, withdraw) undelegationPayouts[delegation.DelegatorAddress] = make(map[common.Address]*big.Int)
}
if totalPayout, ok := undelegationPayouts[delegation.DelegatorAddress][validator]; ok {
undelegationPayouts[delegation.DelegatorAddress][validator] = new(big.Int).Add(totalPayout, withdraw)
} else { } else {
undelegationPayouts[delegation.DelegatorAddress] = withdraw undelegationPayouts[delegation.DelegatorAddress][validator] = withdraw
} }
} }
} }

@ -220,7 +220,7 @@ func GetDelegateOperationForSubAccount(tx *stakingTypes.StakingTransaction, dele
func GetSideEffectOperationsFromUndelegationPayouts( func GetSideEffectOperationsFromUndelegationPayouts(
payouts hmy.UndelegationPayouts, startingOperationIndex *int64, payouts hmy.UndelegationPayouts, startingOperationIndex *int64,
) ([]*types.Operation, *types.Error) { ) ([]*types.Operation, *types.Error) {
return getSideEffectOperationsFromValueMap( return getSideEffectOperationsFromUndelegateMap(
payouts, common.UndelegationPayoutOperation, startingOperationIndex, payouts, common.UndelegationPayoutOperation, startingOperationIndex,
) )
} }
@ -449,6 +449,75 @@ func getCrossShardSenderTransferNativeOperations(
}, nil }, nil
} }
// delegator address => validator address => amount
func getSideEffectOperationsFromUndelegateMap(
valueMap map[ethcommon.Address]map[ethcommon.Address]*big.Int, opType string, startingOperationIndex *int64,
) ([]*types.Operation, *types.Error) {
var opIndex int64
operations := []*types.Operation{}
if startingOperationIndex != nil {
opIndex = *startingOperationIndex
} else {
opIndex = 0
}
for delegator, undelegationMap := range valueMap {
totalAmount := new(big.Int).SetUint64(0)
accID, rosettaError := newAccountIdentifier(delegator)
if rosettaError != nil {
return nil, rosettaError
}
receiverOp := &types.Operation{
OperationIdentifier: &types.OperationIdentifier{
Index: opIndex,
},
Type: opType,
Status: common.SuccessOperationStatus.Status,
Account: accID,
}
opIndex++
operations = append(operations, receiverOp)
receiverIndex := len(operations) - 1
for validator, amount := range undelegationMap {
totalAmount = new(big.Int).Add(totalAmount, amount)
subAccId, rosettaError := newAccountIdentifierWithSubAccount(delegator, validator, map[string]interface{}{
SubAccountMetadataKey: UnDelegation,
})
if rosettaError != nil {
return nil, rosettaError
}
payoutOp := &types.Operation{
OperationIdentifier: &types.OperationIdentifier{
Index: opIndex,
},
RelatedOperations: []*types.OperationIdentifier{
receiverOp.OperationIdentifier,
},
Type: opType,
Status: common.SuccessOperationStatus.Status,
Account: subAccId,
Amount: &types.Amount{
Value: negativeBigValue(amount),
Currency: &common.NativeCurrency,
},
}
operations = append(operations, payoutOp)
opIndex++
}
operations[receiverIndex].Amount = &types.Amount{
Value: totalAmount.String(),
Currency: &common.NativeCurrency,
}
}
return operations, nil
}
// getSideEffectOperationsFromValueMap is a helper for side effect operation construction from a address to value map. // getSideEffectOperationsFromValueMap is a helper for side effect operation construction from a address to value map.
func getSideEffectOperationsFromValueMap( func getSideEffectOperationsFromValueMap(
valueMap map[ethcommon.Address]*big.Int, opType string, startingOperationIndex *int64, valueMap map[ethcommon.Address]*big.Int, opType string, startingOperationIndex *int64,

Loading…
Cancel
Save