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

safe-global / safe-client-gateway / 9546514333

17 Jun 2024 11:01AM UTC coverage: 49.473% (-42.8%) from 92.296%
9546514333

push

github

web-flow
Add `PostgresDatabaseMigrator` for (testing) migration (#1655)

Adds a new `PostgresDatabaseMigrator` that has the core logic of `postgres-shift`, as well as a testing method. The `migrate` method mirrors `postgres-shift` and the `test` method reuses part of it, executing each migration in a separate transaction. It allows us to interact with the database _before_ and _after_ a migration has executed, stopping after the desired migration:

- Create `PostgresDatabaseMigrator` and inject it
- Remove `postgres-shift` and associated definition/patch, replacing usage with the above
- Add appropriate test coverage

394 of 2367 branches covered (16.65%)

Branch coverage included in aggregate %.

10 of 62 new or added lines in 3 files covered. (16.13%)

2191 existing lines in 221 files now uncovered.

3969 of 6452 relevant lines covered (61.52%)

12.49 hits per line

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

18.37
/src/datasources/locking-api/locking-api.service.ts
1
import { IConfigurationService } from '@/config/configuration.service.interface';
16✔
2
import { HttpErrorFactory } from '@/datasources/errors/http-error-factory';
16✔
3
import {
16✔
4
  NetworkService,
5
  INetworkService,
6
} from '@/datasources/network/network.service.interface';
7
import { Page } from '@/domain/entities/page.entity';
8
import { ILockingApi } from '@/domain/interfaces/locking-api.interface';
9
import { Campaign } from '@/domain/community/entities/campaign.entity';
10
import { CampaignRank } from '@/domain/community/entities/campaign-rank.entity';
11
import { LockingEvent } from '@/domain/community/entities/locking-event.entity';
12
import { LockingRank } from '@/domain/community/entities/locking-rank.entity';
13
import { Inject } from '@nestjs/common';
16✔
14

15
export class LockingApi implements ILockingApi {
16✔
16
  private readonly baseUri: string;
17

18
  constructor(
19
    @Inject(IConfigurationService)
20
    private readonly configurationService: IConfigurationService,
16✔
21
    @Inject(NetworkService)
22
    private readonly networkService: INetworkService,
16✔
23
    private readonly httpErrorFactory: HttpErrorFactory,
16✔
24
  ) {
25
    this.baseUri =
16✔
26
      this.configurationService.getOrThrow<string>('locking.baseUri');
27
  }
28

29
  async getCampaignById(resourceId: string): Promise<Campaign> {
UNCOV
30
    try {
×
UNCOV
31
      const url = `${this.baseUri}/api/v1/campaigns/${resourceId}`;
×
UNCOV
32
      const { data } = await this.networkService.get<Campaign>({ url });
×
UNCOV
33
      return data;
×
34
    } catch (error) {
UNCOV
35
      throw this.httpErrorFactory.from(error);
×
36
    }
37
  }
38

39
  async getCampaigns(args: {
40
    limit?: number;
41
    offset?: number;
42
  }): Promise<Page<Campaign>> {
UNCOV
43
    try {
×
UNCOV
44
      const url = `${this.baseUri}/api/v1/campaigns`;
×
UNCOV
45
      const { data } = await this.networkService.get<Page<Campaign>>({
×
46
        url,
47
        networkRequest: {
48
          params: {
49
            limit: args.limit,
50
            offset: args.offset,
51
          },
52
        },
53
      });
UNCOV
54
      return data;
×
55
    } catch (error) {
UNCOV
56
      throw this.httpErrorFactory.from(error);
×
57
    }
58
  }
59

60
  async getCampaignActivities(args: {
61
    resourceId: string;
62
    holder?: `0x${string}`;
63
    limit?: number;
64
    offset?: number;
65
  }): Promise<number> {
UNCOV
66
    try {
×
UNCOV
67
      const url = `${this.baseUri}/api/v1/campaigns/${args.resourceId}/activities`;
×
UNCOV
68
      const { data } = await this.networkService.get<number>({
×
69
        url,
70
        networkRequest: {
71
          params: {
72
            holder: args.holder,
73
            limit: args.limit,
74
            offset: args.offset,
75
          },
76
        },
77
      });
UNCOV
78
      return data;
×
79
    } catch (error) {
UNCOV
80
      throw this.httpErrorFactory.from(error);
×
81
    }
82
  }
83

84
  async getCampaignRank(args: {
85
    resourceId: string;
86
    safeAddress: `0x${string}`;
87
  }): Promise<CampaignRank> {
UNCOV
88
    try {
×
UNCOV
89
      const url = `${this.baseUri}/api/v1/campaigns/${args.resourceId}/leaderboard/${args.safeAddress}`;
×
UNCOV
90
      const { data } = await this.networkService.get<CampaignRank>({ url });
×
UNCOV
91
      return data;
×
92
    } catch (error) {
UNCOV
93
      throw this.httpErrorFactory.from(error);
×
94
    }
95
  }
96

97
  async getLockingRank(safeAddress: `0x${string}`): Promise<LockingRank> {
UNCOV
98
    try {
×
UNCOV
99
      const url = `${this.baseUri}/api/v1/leaderboard/${safeAddress}`;
×
UNCOV
100
      const { data } = await this.networkService.get<LockingRank>({ url });
×
UNCOV
101
      return data;
×
102
    } catch (error) {
UNCOV
103
      throw this.httpErrorFactory.from(error);
×
104
    }
105
  }
106

107
  async getLeaderboard(args: {
108
    limit?: number;
109
    offset?: number;
110
  }): Promise<Page<LockingRank>> {
UNCOV
111
    try {
×
UNCOV
112
      const url = `${this.baseUri}/api/v1/leaderboard`;
×
UNCOV
113
      const { data } = await this.networkService.get<Page<LockingRank>>({
×
114
        url,
115
        networkRequest: {
116
          params: {
117
            limit: args.limit,
118
            offset: args.offset,
119
          },
120
        },
121
      });
UNCOV
122
      return data;
×
123
    } catch (error) {
UNCOV
124
      throw this.httpErrorFactory.from(error);
×
125
    }
126
  }
127

128
  async getCampaignLeaderboard(args: {
129
    resourceId: string;
130
    limit?: number;
131
    offset?: number;
132
  }): Promise<Page<CampaignRank>> {
UNCOV
133
    try {
×
UNCOV
134
      const url = `${this.baseUri}/api/v1/campaigns/${args.resourceId}/leaderboard`;
×
UNCOV
135
      const { data } = await this.networkService.get<Page<CampaignRank>>({
×
136
        url,
137
        networkRequest: {
138
          params: {
139
            limit: args.limit,
140
            offset: args.offset,
141
          },
142
        },
143
      });
UNCOV
144
      return data;
×
145
    } catch (error) {
UNCOV
146
      throw this.httpErrorFactory.from(error);
×
147
    }
148
  }
149

150
  async getLockingHistory(args: {
151
    safeAddress: `0x${string}`;
152
    limit?: number;
153
    offset?: number;
154
  }): Promise<Page<LockingEvent>> {
UNCOV
155
    try {
×
UNCOV
156
      const url = `${this.baseUri}/api/v1/all-events/${args.safeAddress}`;
×
UNCOV
157
      const { data } = await this.networkService.get<Page<LockingEvent>>({
×
158
        url,
159
        networkRequest: {
160
          params: {
161
            limit: args.limit,
162
            offset: args.offset,
163
          },
164
        },
165
      });
UNCOV
166
      return data;
×
167
    } catch (error) {
UNCOV
168
      throw this.httpErrorFactory.from(error);
×
169
    }
170
  }
171
}
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

© 2026 Coveralls, Inc