From e2d4265bb93f90813b962da5e686ea39f257a703 Mon Sep 17 00:00:00 2001 From: Madhur Shrimal Date: Wed, 8 Jun 2022 13:43:37 -0700 Subject: [PATCH] add sub account optional flag (#414) * add subaccount optional flag * added subaccount validation with optional param * gen * comments --- parser/match_operations.go | 44 +++++++++++--- parser/match_operations_test.go | 104 +++++++++++++++++++++++++++++++- 2 files changed, 138 insertions(+), 10 deletions(-) diff --git a/parser/match_operations.go b/parser/match_operations.go index 0a1a7205..fc2a0d80 100644 --- a/parser/match_operations.go +++ b/parser/match_operations.go @@ -1,4 +1,4 @@ -// Copyright 2020 Coinbase, Inc. +// Copyright 2022 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -105,7 +105,11 @@ type MetadataDescription struct { // AccountDescription is used to describe a *types.AccountIdentifier. type AccountDescription struct { - Exists bool + Exists bool + + // SubAccountOptional If this is true then SubAccountExists, SubAccountAddress, + // SubAccountMetadataKeys matching is ignored + SubAccountOptional bool SubAccountExists bool SubAccountAddress string SubAccountMetadataKeys []*MetadataDescription @@ -213,6 +217,16 @@ func accountMatch(req *AccountDescription, account *types.AccountIdentifier) err return nil } + if req.SubAccountOptional { + // Optionally can require a certain subaccount address if subaccount is present + if account.SubAccount != nil { + if err := verifySubAccountAddress(req.SubAccountAddress, account.SubAccount); err != nil { + return err + } + } + return nil + } + if account.SubAccount == nil { if req.SubAccountExists { return ErrAccountMatchSubAccountMissing @@ -226,13 +240,8 @@ func accountMatch(req *AccountDescription, account *types.AccountIdentifier) err } // Optionally can require a certain subaccount address - if len(req.SubAccountAddress) > 0 && account.SubAccount.Address != req.SubAccountAddress { - return fmt.Errorf( - "%w: expected %s but got %s", - ErrAccountMatchUnexpectedSubAccountAddr, - req.SubAccountAddress, - account.SubAccount.Address, - ) + if err := verifySubAccountAddress(req.SubAccountAddress, account.SubAccount); err != nil { + return err } if err := metadataMatch(req.SubAccountMetadataKeys, account.SubAccount.Metadata); err != nil { @@ -242,6 +251,23 @@ func accountMatch(req *AccountDescription, account *types.AccountIdentifier) err return nil } +// verifySubAccountAddress verifies the sub-account address if +// sub-account is present. +func verifySubAccountAddress( + subAccountAddress string, + subAccount *types.SubAccountIdentifier, +) error { + if len(subAccountAddress) > 0 && subAccount.Address != subAccountAddress { + return fmt.Errorf( + "%w: expected %s but got %s", + ErrAccountMatchUnexpectedSubAccountAddr, + subAccountAddress, + subAccount.Address, + ) + } + return nil +} + // amountMatch returns an error if a *types.Amount does not meet an // *AmountDescription. func amountMatch(req *AmountDescription, amount *types.Amount) error { diff --git a/parser/match_operations_test.go b/parser/match_operations_test.go index 9b25c314..f917f1f8 100644 --- a/parser/match_operations_test.go +++ b/parser/match_operations_test.go @@ -1,4 +1,4 @@ -// Copyright 2020 Coinbase, Inc. +// Copyright 2022 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -1408,6 +1408,108 @@ func TestMatchOperations(t *testing.T) { matches: nil, err: true, }, + "sub account optional - when sub-account exist": { + operations: []*types.Operation{ + { + Account: &types.AccountIdentifier{ + Address: "addr1", + SubAccount: &types.SubAccountIdentifier{ + Address: "sub 2", + }, + }, + }, + { + Account: &types.AccountIdentifier{ + Address: "addr2", + }, + }, + }, + descriptions: &Descriptions{ + OperationDescriptions: []*OperationDescription{ + { + Account: &AccountDescription{ + Exists: true, + SubAccountOptional: true, + SubAccountExists: true, + SubAccountAddress: "sub 2", + }, + }, + { + Account: &AccountDescription{ + Exists: true, + SubAccountOptional: true, + SubAccountExists: true, + SubAccountAddress: "sub 1", + }, + }, + }, + }, + matches: []*Match{ + { + Operations: []*types.Operation{ + { + Account: &types.AccountIdentifier{ + Address: "addr1", + SubAccount: &types.SubAccountIdentifier{ + Address: "sub 2", + }, + }, + }, + }, + Amounts: []*big.Int{nil}, + }, + { + Operations: []*types.Operation{ + { + Account: &types.AccountIdentifier{ + Address: "addr2", + }, + }, + }, + Amounts: []*big.Int{nil}, + }, + }, + err: false, + }, + "sub account optional - when sub-account address is different": { + operations: []*types.Operation{ + { + Account: &types.AccountIdentifier{ + Address: "addr1", + SubAccount: &types.SubAccountIdentifier{ + Address: "sub 2", + }, + }, + }, + { + Account: &types.AccountIdentifier{ + Address: "addr2", + }, + }, + }, + descriptions: &Descriptions{ + OperationDescriptions: []*OperationDescription{ + { + Account: &AccountDescription{ + Exists: true, + SubAccountOptional: true, + SubAccountExists: true, + SubAccountAddress: "sub 3", + }, + }, + { + Account: &AccountDescription{ + Exists: true, + SubAccountOptional: true, + SubAccountExists: true, + SubAccountAddress: "sub 1", + }, + }, + }, + }, + matches: nil, + err: true, + }, "nil descriptions": { operations: []*types.Operation{ {