• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

safe-global / safe-client-gateway-nest / 5941127155

22 Aug 2023 03:52PM UTC coverage: 92.245%. First build
5941127155

Pull #631

github

GitHub
Merge daff89e0f into c8aa71879
Pull Request #631:

966 of 1156 branches covered (83.56%)

Branch coverage included in aggregate %.

127 of 144 new or added lines in 22 files covered. (88.19%)

4494 of 4763 relevant lines covered (94.35%)

72.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.57
/src/domain/human-description/human-description.repository.ts
1
import { Inject, Injectable } from '@nestjs/common';
33✔
2
import { IHumanDescriptionRepository } from './human-description.repository.interface';
3
import {
33✔
4
  HumanDescriptionFragment,
5
  HumanDescriptions,
6
  HumanDescriptionTemplates,
7
  ValueType,
8
} from './entities/human-description.entity';
9
import { IHumanDescriptionApi } from '../interfaces/human-description-api.interface';
33✔
10
import { getFunctionSelector, parseAbi } from 'viem';
33✔
11

12
@Injectable()
13
export class HumanDescriptionRepository implements IHumanDescriptionRepository {
33✔
14
  private readonly parsedDescriptions: HumanDescriptionTemplates;
15

16
  /**
17
   *  Regex Template that matches two patterns
18
   *  1. Double curly braces consisting of 2 groups separated by a space
19
   *  2. Any non-whitespace character i.e. simple words
20
   */
21
  private static readonly TEMPLATE_REGEX = /{{(.*?)\s(\$.*?)}}|(\S+)/g;
33✔
22

23
  constructor(
24
    @Inject(IHumanDescriptionApi)
25
    private readonly humanDescriptionApi: IHumanDescriptionApi,
211✔
26
  ) {
27
    const humanDescriptions = this.humanDescriptionApi.getDescriptions();
211✔
28
    this.parsedDescriptions = this.parseDescriptions(humanDescriptions);
211✔
29
  }
30

31
  getDescriptions(): HumanDescriptionTemplates {
32
    return this.parsedDescriptions;
42✔
33
  }
34

35
  parseDescriptions(
36
    descriptions: HumanDescriptions,
37
  ): HumanDescriptionTemplates {
38
    const templates: HumanDescriptionTemplates = {};
211✔
39

40
    for (const signature in descriptions) {
211✔
41
      const template = descriptions[signature];
2,532✔
42
      const sigHash = getFunctionSelector(signature);
2,532✔
43
      const abi = parseAbi([signature]);
2,532✔
44

45
      templates[sigHash] = {
2,532✔
46
        abi,
47
        process: (to: string, params: unknown[]) => {
48
          const fragments: HumanDescriptionFragment[] = [];
5✔
49

50
          let match: RegExpExecArray | null;
51

52
          while (
5✔
53
            (match =
54
              HumanDescriptionRepository.TEMPLATE_REGEX.exec(template)) !== null
55
          ) {
56
            const [fullMatch, valueType, valueIndexPrefixed] = match;
18✔
57

58
            if (valueType !== undefined && !this.isValueType(valueType))
18!
NEW
59
              continue;
×
60

61
            // Matched a simple string
62
            if (fullMatch && !valueType && !valueIndexPrefixed) {
18✔
63
              fragments.push({
9✔
64
                type: ValueType.Word,
65
                value: fullMatch,
66
              });
67
              continue;
9✔
68
            }
69

70
            // Slice the first character of the valueIndex to remove $ prefix
71
            const valueIndex = valueIndexPrefixed.slice(1);
9✔
72

73
            const parsedExpression = this.parseExpression(
9✔
74
              valueType,
75
              Number(valueIndex),
76
              to,
77
              params,
78
            );
79

80
            if (parsedExpression) {
9✔
81
              fragments.push(parsedExpression);
9✔
82
            }
83
          }
84

85
          return fragments;
5✔
86
        },
87
      };
88
    }
89

90
    return templates;
211✔
91
  }
92

93
  parseExpression(
94
    valueType: ValueType,
95
    valueIndex: number,
96
    to: string,
97
    params: unknown[],
98
  ): HumanDescriptionFragment | null {
99
    try {
9✔
100
      const parsedParam = this.parseParam(valueType, valueIndex, to, params);
9✔
101

102
      return <HumanDescriptionFragment>{
9✔
103
        type: valueType,
104
        value: parsedParam,
105
      };
106
    } catch (error) {
NEW
107
      return null;
×
108
    }
109
  }
110

111
  parseParam(
112
    valueType: ValueType,
113
    valueIndex: number,
114
    to: string,
115
    params: unknown[],
116
  ): HumanDescriptionFragment['value'] {
117
    switch (valueType) {
9!
118
      case ValueType.TokenValue:
119
        return {
5✔
120
          amount: params[valueIndex],
121
          address: to,
122
        };
123
      case ValueType.Address:
124
      case ValueType.Decimals:
125
      case ValueType.Identifier:
126
      case ValueType.Word:
127
        return params[valueIndex];
4✔
128
      default:
NEW
129
        throw Error(`${valueType} is not allowed as ValueType`);
×
130
    }
131
  }
132

133
  private isValueType(type: unknown): type is ValueType {
134
    return Object.values(ValueType).includes(type as ValueType);
9✔
135
  }
136
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc