github.com/status-im/status-go@v1.1.0/protocol/communities/permission_checker_test.go (about) 1 package communities 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "math/big" 8 "strconv" 9 "testing" 10 11 "github.com/stretchr/testify/suite" 12 13 "github.com/status-im/status-go/protocol/protobuf" 14 "github.com/status-im/status-go/services/wallet/bigint" 15 "github.com/status-im/status-go/services/wallet/thirdparty" 16 17 gethcommon "github.com/ethereum/go-ethereum/common" 18 "github.com/ethereum/go-ethereum/common/hexutil" 19 ) 20 21 func TestPermissionCheckerSuite(t *testing.T) { 22 suite.Run(t, new(PermissionCheckerSuite)) 23 } 24 25 type PermissionCheckerSuite struct { 26 suite.Suite 27 } 28 29 func (s *PermissionCheckerSuite) TestMergeValidCombinations() { 30 31 permissionChecker := DefaultPermissionChecker{} 32 33 combination1 := &AccountChainIDsCombination{ 34 Address: gethcommon.HexToAddress("0xA"), 35 ChainIDs: []uint64{1}, 36 } 37 38 combination2 := &AccountChainIDsCombination{ 39 Address: gethcommon.HexToAddress("0xB"), 40 ChainIDs: []uint64{5}, 41 } 42 43 combination3 := &AccountChainIDsCombination{ 44 Address: gethcommon.HexToAddress("0xA"), 45 ChainIDs: []uint64{5}, 46 } 47 48 combination4 := &AccountChainIDsCombination{ 49 Address: gethcommon.HexToAddress("0xB"), 50 ChainIDs: []uint64{5}, 51 } 52 53 mergedCombination := permissionChecker.MergeValidCombinations([]*AccountChainIDsCombination{combination1, combination2}, 54 []*AccountChainIDsCombination{combination3, combination4}) 55 56 s.Require().Len(mergedCombination, 2) 57 chains1 := mergedCombination[0].ChainIDs 58 chains2 := mergedCombination[1].ChainIDs 59 60 if len(chains1) == 2 { 61 s.Equal([]uint64{1, 5}, chains1) 62 s.Equal([]uint64{5}, chains2) 63 } else { 64 s.Equal([]uint64{1, 5}, chains2) 65 s.Equal([]uint64{5}, chains1) 66 } 67 68 } 69 70 func (s *PermissionCheckerSuite) TestCheckPermissions() { 71 testCases := []struct { 72 name string 73 amountInWei func(t protobuf.CommunityTokenType) string 74 requiredAmountInWei func(t protobuf.CommunityTokenType) string 75 shouldSatisfy bool 76 }{ 77 { 78 name: "account does not meet criteria", 79 amountInWei: func(t protobuf.CommunityTokenType) string { 80 if t == protobuf.CommunityTokenType_ERC721 { 81 return "1" 82 } 83 return "1000000000000000000" 84 }, 85 requiredAmountInWei: func(t protobuf.CommunityTokenType) string { 86 if t == protobuf.CommunityTokenType_ERC721 { 87 return "2" 88 } 89 return "2000000000000000000" 90 }, 91 shouldSatisfy: false, 92 }, 93 { 94 name: "account does exactly meet criteria", 95 amountInWei: func(t protobuf.CommunityTokenType) string { 96 if t == protobuf.CommunityTokenType_ERC721 { 97 return "2" 98 } 99 return "2000000000000000000" 100 }, 101 requiredAmountInWei: func(t protobuf.CommunityTokenType) string { 102 if t == protobuf.CommunityTokenType_ERC721 { 103 return "2" 104 } 105 return "2000000000000000000" 106 }, 107 shouldSatisfy: true, 108 }, 109 { 110 name: "account does meet criteria", 111 amountInWei: func(t protobuf.CommunityTokenType) string { 112 if t == protobuf.CommunityTokenType_ERC721 { 113 return "3" 114 } 115 return "3000000000000000000" 116 }, 117 requiredAmountInWei: func(t protobuf.CommunityTokenType) string { 118 if t == protobuf.CommunityTokenType_ERC721 { 119 return "2" 120 } 121 return "2000000000000000000" 122 }, 123 shouldSatisfy: true, 124 }, 125 } 126 127 permissionChecker := DefaultPermissionChecker{} 128 chainID := uint64(1) 129 contractAddress := gethcommon.HexToAddress("0x3d6afaa395c31fcd391fe3d562e75fe9e8ec7e6a") 130 walletAddress := gethcommon.HexToAddress("0xD6b912e09E797D291E8D0eA3D3D17F8000e01c32") 131 132 for _, tc := range testCases { 133 for _, tokenType := range [](protobuf.CommunityTokenType){protobuf.CommunityTokenType_ERC20, protobuf.CommunityTokenType_ERC721} { 134 s.Run(fmt.Sprintf("%s_%s", tc.name, tokenType.String()), func() { 135 decimals := uint64(0) 136 if tokenType == protobuf.CommunityTokenType_ERC20 { 137 decimals = 18 138 } 139 permissions := map[string]*CommunityTokenPermission{ 140 "p1": { 141 CommunityTokenPermission: &protobuf.CommunityTokenPermission{ 142 Id: "p1", 143 Type: protobuf.CommunityTokenPermission_BECOME_MEMBER, 144 TokenCriteria: []*protobuf.TokenCriteria{ 145 { 146 ContractAddresses: map[uint64]string{ 147 chainID: contractAddress.String(), 148 }, 149 Type: tokenType, 150 Symbol: "STT", 151 TokenIds: []uint64{}, 152 Decimals: decimals, 153 AmountInWei: tc.requiredAmountInWei(tokenType), 154 }, 155 }, 156 }, 157 }, 158 } 159 160 permissionsData, _ := PreParsePermissionsData(permissions) 161 accountsAndChainIDs := []*AccountChainIDsCombination{ 162 { 163 Address: walletAddress, 164 ChainIDs: []uint64{chainID}, 165 }, 166 } 167 168 var getOwnedERC721Tokens ownedERC721TokensGetter = func(walletAddresses []gethcommon.Address, tokenRequirements map[uint64]map[string]*protobuf.TokenCriteria, chainIDs []uint64) (CollectiblesByChain, error) { 169 amount, err := strconv.ParseUint(tc.amountInWei(protobuf.CommunityTokenType_ERC721), 10, 64) 170 if err != nil { 171 return nil, err 172 } 173 174 balances := []thirdparty.TokenBalance{} 175 for i := uint64(0); i < amount; i++ { 176 balances = append(balances, thirdparty.TokenBalance{ 177 TokenID: &bigint.BigInt{ 178 Int: new(big.Int).SetUint64(i + 1), 179 }, 180 Balance: &bigint.BigInt{ 181 Int: new(big.Int).SetUint64(1), 182 }, 183 }) 184 } 185 186 return CollectiblesByChain{ 187 chainID: { 188 walletAddress: { 189 contractAddress: balances, 190 }, 191 }, 192 }, nil 193 } 194 195 var getBalancesByChain balancesByChainGetter = func(ctx context.Context, accounts, tokens []gethcommon.Address, chainIDs []uint64) (BalancesByChain, error) { 196 balance, ok := new(big.Int).SetString(tc.amountInWei(protobuf.CommunityTokenType_ERC20), 10) 197 if !ok { 198 return nil, errors.New("invalid conversion") 199 } 200 201 return BalancesByChain{ 202 chainID: { 203 walletAddress: { 204 contractAddress: (*hexutil.Big)(balance), 205 }, 206 }, 207 }, nil 208 } 209 210 response, err := permissionChecker.checkPermissions(permissionsData[protobuf.CommunityTokenPermission_BECOME_MEMBER], accountsAndChainIDs, true, getOwnedERC721Tokens, getBalancesByChain) 211 s.Require().NoError(err) 212 s.Require().Equal(tc.shouldSatisfy, response.Satisfied) 213 }) 214 } 215 } 216 }