@aurigami/sdk 1.4.8 → 1.5.0-dummy-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,282 +1,327 @@
1
- import { Provider } from "@ethersproject/abstract-provider";
1
+ import { Provider } from '@ethersproject/abstract-provider';
2
2
  import { TransactionResponse } from '@ethersproject/abstract-provider';
3
- import { BlockchainEntity, BlockchainEntityRead } from "./BlockchainEntity";
4
- import { Address, NetworkConnection } from "./types";
5
- import { BigNumber as BN, Contract, utils } from "ethers";
6
- import { TransferEventQuery } from "./transfer-event-query";
7
- import { AIRDROP_START_TIMESTAMP, AIRDROP_KEEP_THRESHOLD, AIRDROP_END_TIMESTAMP, networkAddresses } from "./constants";
8
- import AuriAirdropABI from "@aurigami/contracts/artifacts/contracts/AuriAirdrop.sol/AuriAirdrop.json"
9
- import { getBlockBeforeTimestamp, getCurrentTimestamp, getDecimal, isSameAddress } from "./helpers";
10
- import AIRDROP_AUTOKEN_INFO from "./airdrop_misc/auTokensInfo.json"
11
- import AIRDROP_WHITELIST_ADDRESSES from "./airdrop_misc/whitelist.json"
12
- import { AuriAirdrop } from "@aurigami/contracts/typechain";
3
+ import { BlockchainEntity, BlockchainEntityRead } from './BlockchainEntity';
4
+ import { Address, NetworkConnection } from './types';
5
+ import { BigNumber as BN, Contract, utils } from 'ethers';
6
+ import { TransferEventQuery } from './transfer-event-query';
7
+ import {
8
+ AIRDROP_START_TIMESTAMP,
9
+ AIRDROP_KEEP_THRESHOLD,
10
+ AIRDROP_END_TIMESTAMP,
11
+ networkAddresses,
12
+ } from './constants';
13
+ import AuriAirdropABI from '@aurigami/contracts/artifacts/contracts/AuriAirdrop.sol/AuriAirdrop.json';
14
+ import {
15
+ getBlockBeforeTimestamp,
16
+ getCurrentTimestamp,
17
+ getDecimal,
18
+ isSameAddress,
19
+ } from './helpers';
20
+ import AIRDROP_AUTOKEN_INFO from './airdrop_misc/auTokensInfo.json';
21
+ import AIRDROP_WHITELIST_ADDRESSES from './airdrop_misc/whitelist.json';
22
+ import { AuriAirdrop } from '@aurigami/contracts/typechain';
13
23
  import assert from 'assert';
14
- import { TokenAmount } from "./tokenAmount";
15
- import { Token } from "./token";
24
+ import { TokenAmount } from './tokenAmount';
25
+ import { Token } from './token';
16
26
 
17
27
  type AirdropUnderlyingInfo = {
18
- minDeposit: BN,
19
- }
28
+ minDeposit: BN;
29
+ };
20
30
 
21
31
  type AirdropAuTokenInfo = {
22
- address: string,
23
- exchangeRate: BN,
24
- deploymentBlock: number,
25
- underlying: AirdropUnderlyingInfo
26
- }
32
+ address: string;
33
+ exchangeRate: BN;
34
+ deploymentBlock: number;
35
+ underlying: AirdropUnderlyingInfo;
36
+ };
27
37
 
28
38
  class AirdropSettings {
29
- private static _instance: AirdropSettings;
30
-
31
- airdropStartBlock: number = 0;
32
- airdropEndBlock: number = 0;
33
- airdropStartTimestamp: number = AIRDROP_START_TIMESTAMP;
34
- airdropEndTimestamp: number = AIRDROP_END_TIMESTAMP;
35
- airdropThreshold: number = AIRDROP_KEEP_THRESHOLD;
36
- private constructor() {}
37
-
38
- public static async getSettings(provider: Provider): Promise<AirdropSettings> {
39
- if (this._instance)
40
- return this._instance;
41
-
42
- let settings: AirdropSettings = new AirdropSettings();
43
-
44
- settings.airdropStartBlock = await getBlockBeforeTimestamp(
45
- provider,
46
- settings.airdropStartTimestamp,
47
- );
48
-
49
- settings.airdropEndBlock = await getBlockBeforeTimestamp(
50
- provider,
51
- settings.airdropEndTimestamp,
52
- );
53
-
54
- this._instance = settings;
55
- return settings;
56
- }
39
+ private static _instance: AirdropSettings;
40
+
41
+ airdropStartBlock: number = 0;
42
+ airdropEndBlock: number = 0;
43
+ airdropStartTimestamp: number = AIRDROP_START_TIMESTAMP;
44
+ airdropEndTimestamp: number = AIRDROP_END_TIMESTAMP;
45
+ airdropThreshold: number = AIRDROP_KEEP_THRESHOLD;
46
+ private constructor() {}
47
+
48
+ public static async getSettings(
49
+ provider: Provider
50
+ ): Promise<AirdropSettings> {
51
+ if (this._instance) return this._instance;
52
+
53
+ let settings: AirdropSettings = new AirdropSettings();
54
+
55
+ settings.airdropStartBlock = await getBlockBeforeTimestamp(
56
+ provider,
57
+ settings.airdropStartTimestamp
58
+ );
59
+
60
+ settings.airdropEndBlock = await getBlockBeforeTimestamp(
61
+ provider,
62
+ settings.airdropEndTimestamp
63
+ );
64
+
65
+ this._instance = settings;
66
+ return settings;
67
+ }
57
68
  }
58
69
 
59
70
  class AirdropAuTokenKeepTracker extends BlockchainEntityRead {
60
- private _transferQuery: TransferEventQuery;
61
- private _airdropAuTokenInfo: AirdropAuTokenInfo;
62
- public constructor(networkConnection: NetworkConnection, airdropAuTokenInfo: AirdropAuTokenInfo) {
63
- super(networkConnection);
64
- this._transferQuery = new TransferEventQuery(airdropAuTokenInfo.address, networkConnection);
65
- this._airdropAuTokenInfo = airdropAuTokenInfo;
66
-
67
- // exchangeRate = 102% * exchangeRate, see why in the comment of _toUnderlyingValue
68
- this._airdropAuTokenInfo.exchangeRate = this._airdropAuTokenInfo.exchangeRate.add(
69
- this._airdropAuTokenInfo.exchangeRate.div(50)
70
- )
71
- }
72
-
73
- /**
74
- * Convert the given amount of auToken to the underlying value with the stored exchange rate
75
- *
76
- * Why we need to do this?
77
- *
78
- * By transfer event, we cannot know the exact underlying, the only
79
- * info that we can keep track of via transfer is event is the auToken amount. So we need to
80
- * convert it to the underlying value with the stored exchange rate.
81
- *
82
- * However, we cannot just simply use auTokenAmount * exchangeRate, because the exchange rate
83
- * is changing over time. As advice of the contract team, use fixed exchangeRate * 102% is good enough.
84
- *
85
- */
86
- private _toUnderlyingValue(auTokenAmount: BN): BN {
87
- return auTokenAmount.mul(
88
- this._airdropAuTokenInfo.exchangeRate
89
- ).div(BN.from(10).pow(18));
71
+ private _transferQuery: TransferEventQuery;
72
+ private _airdropAuTokenInfo: AirdropAuTokenInfo;
73
+ public constructor(
74
+ networkConnection: NetworkConnection,
75
+ airdropAuTokenInfo: AirdropAuTokenInfo
76
+ ) {
77
+ super(networkConnection);
78
+ this._transferQuery = new TransferEventQuery(
79
+ airdropAuTokenInfo.address,
80
+ networkConnection
81
+ );
82
+ this._airdropAuTokenInfo = airdropAuTokenInfo;
83
+
84
+ // exchangeRate = 102% * exchangeRate, see why in the comment of _toUnderlyingValue
85
+ this._airdropAuTokenInfo.exchangeRate =
86
+ this._airdropAuTokenInfo.exchangeRate.add(
87
+ this._airdropAuTokenInfo.exchangeRate.div(50)
88
+ );
89
+ }
90
+
91
+ /**
92
+ * Convert the given amount of auToken to the underlying value with the stored exchange rate
93
+ *
94
+ * Why we need to do this?
95
+ *
96
+ * By transfer event, we cannot know the exact underlying, the only
97
+ * info that we can keep track of via transfer is event is the auToken amount. So we need to
98
+ * convert it to the underlying value with the stored exchange rate.
99
+ *
100
+ * However, we cannot just simply use auTokenAmount * exchangeRate, because the exchange rate
101
+ * is changing over time. As advice of the contract team, use fixed exchangeRate * 102% is good enough.
102
+ *
103
+ */
104
+ private _toUnderlyingValue(auTokenAmount: BN): BN {
105
+ return auTokenAmount
106
+ .mul(this._airdropAuTokenInfo.exchangeRate)
107
+ .div(BN.from(10).pow(18));
108
+ }
109
+
110
+ /**
111
+ * Check if the user has been deposit at least (minDeposit) and keep it for
112
+ * more than AIRDROP_KEEP_THRESHOLD milliseconds
113
+ *
114
+ * How it works:
115
+ * Whenever the user balance is exceed minDeposit, we will record the timestamp,
116
+ * and when the balance is below minDeposit, we will compare with the saved timestamp to see
117
+ * whether it has been keep for more than AIRDROP_KEEP_THRESHOLD milliseconds.
118
+ *
119
+ */
120
+ public async isEligible(address: string): Promise<boolean> {
121
+ const settings = await AirdropSettings.getSettings(
122
+ this._networkConnection.provider
123
+ );
124
+ const minDeposit = this._airdropAuTokenInfo.underlying.minDeposit;
125
+
126
+ // Get user balance at the time of Airdrop start
127
+ let balance = await this._transferQuery.queryERC20BalanceAt(
128
+ address,
129
+ settings.airdropStartBlock - 1
130
+ );
131
+
132
+ const [BELOW, ABOVE] = [false, true];
133
+ let flag = BELOW;
134
+ // variable to store the last timestamp that, from it to "current" timestamp,
135
+ // the balance is always above minDeposit
136
+ let lastEligibleBalanceTimestamp = 0;
137
+
138
+ if (this._toUnderlyingValue(balance).gte(minDeposit)) {
139
+ lastEligibleBalanceTimestamp = settings.airdropStartTimestamp;
140
+ flag = ABOVE;
90
141
  }
91
142
 
92
- /**
93
- * Check if the user has been deposit at least (minDeposit) and keep it for
94
- * more than AIRDROP_KEEP_THRESHOLD milliseconds
95
- *
96
- * How it works:
97
- * Whenever the user balance is exceed minDeposit, we will record the timestamp,
98
- * and when the balance is below minDeposit, we will compare with the saved timestamp to see
99
- * whether it has been keep for more than AIRDROP_KEEP_THRESHOLD milliseconds.
100
- *
101
- */
102
- public async isEligible(address: string): Promise<boolean> {
103
- const settings = await AirdropSettings.getSettings(this._networkConnection.provider);
104
- const minDeposit = this._airdropAuTokenInfo.underlying.minDeposit;
105
-
106
- // Get user balance at the time of Airdrop start
107
- let balance = await this._transferQuery.queryERC20BalanceAt(
108
- address,
109
- settings.airdropStartBlock - 1
110
- );
111
-
112
- const [BELOW, ABOVE] = [false, true];
113
- let flag = BELOW;
114
- // variable to store the last timestamp that, from it to "current" timestamp,
115
- // the balance is always above minDeposit
116
- let lastEligibleBalanceTimestamp = 0;
117
-
118
- if (this._toUnderlyingValue(balance).gte(minDeposit)) {
119
- lastEligibleBalanceTimestamp = settings.airdropStartTimestamp;
120
- flag = ABOVE;
121
- }
122
-
123
- let events = await this._transferQuery.queryERC20TransfersOf(
124
- address,
125
- settings.airdropStartBlock,
126
- settings.airdropEndBlock
127
- );
128
-
129
- for (let { from, to, amount, blockNumber } of events) {
130
- if (isSameAddress(from, address)) {
131
- balance = balance.sub(amount);
132
- }
133
- if (isSameAddress(to, address)) {
134
- balance = balance.add(amount);
135
- }
136
-
137
- // if it is different from the flag, that means the balance is changing
138
- if (this._toUnderlyingValue(balance).gte(minDeposit) != flag) {
139
- flag = !flag;
140
- const timestamp = (await this._networkConnection.provider.getBlock(blockNumber)).timestamp;
141
-
142
- // if this txn make the balance below the minDeposit,
143
- // check whether it has been keep for more than AIRDROP_KEEP_THRESHOLD
144
- if (flag == BELOW) {
145
- if (timestamp - lastEligibleBalanceTimestamp >= settings.airdropThreshold) {
146
- return true;
147
- }
148
- lastEligibleBalanceTimestamp = 0;
149
- }
150
- else {
151
- // record the timestamp when the balance is above minDeposit
152
- lastEligibleBalanceTimestamp = timestamp;
153
- }
154
- }
155
- }
156
-
157
- // if after the last txn, the balance is still above minDeposit,
158
- // we should check from the last timestamp to "now"
159
- if (flag == ABOVE) {
160
- const timestamp = Math.min(settings.airdropEndTimestamp, getCurrentTimestamp());
161
- return timestamp - lastEligibleBalanceTimestamp >= settings.airdropThreshold;
143
+ let events = await this._transferQuery.queryERC20TransfersOf(
144
+ address,
145
+ settings.airdropStartBlock,
146
+ settings.airdropEndBlock
147
+ );
148
+
149
+ for (let { from, to, amount, blockNumber } of events) {
150
+ if (isSameAddress(from, address)) {
151
+ balance = balance.sub(amount);
152
+ }
153
+ if (isSameAddress(to, address)) {
154
+ balance = balance.add(amount);
155
+ }
156
+
157
+ // if it is different from the flag, that means the balance is changing
158
+ if (this._toUnderlyingValue(balance).gte(minDeposit) != flag) {
159
+ flag = !flag;
160
+ const timestamp = (
161
+ await this._networkConnection.provider.getBlock(blockNumber)
162
+ ).timestamp;
163
+
164
+ // if this txn make the balance below the minDeposit,
165
+ // check whether it has been keep for more than AIRDROP_KEEP_THRESHOLD
166
+ if (flag == BELOW) {
167
+ if (
168
+ timestamp - lastEligibleBalanceTimestamp >=
169
+ settings.airdropThreshold
170
+ ) {
171
+ return true;
172
+ }
173
+ lastEligibleBalanceTimestamp = 0;
174
+ } else {
175
+ // record the timestamp when the balance is above minDeposit
176
+ lastEligibleBalanceTimestamp = timestamp;
162
177
  }
163
-
164
- return false;
178
+ }
165
179
  }
166
- }
167
180
 
168
- export class AirdropRead extends BlockchainEntityRead {
169
- protected _airDrop: AuriAirdrop;
170
- private _whitelistedAddresses: Set<string>;
171
- private keepTrackers: AirdropAuTokenKeepTracker[] = [];
172
- public constructor(networkConnection: NetworkConnection) {
173
- super(networkConnection);
174
- this._airDrop = new Contract(
175
- networkAddresses.misc.AURI_AIRDROP,
176
- AuriAirdropABI.abi,
177
- networkConnection.provider
178
- ) as AuriAirdrop;
179
-
180
- this._whitelistedAddresses = new Set(
181
- (AIRDROP_WHITELIST_ADDRESSES as string[]).map(e => e.toLocaleLowerCase())
182
- );
183
-
184
- let auTokens: any = AIRDROP_AUTOKEN_INFO;
185
-
186
- for (let auToken in auTokens) {
187
- let { address, exchangeRate, deploymentBlock, underlying } = auTokens[auToken];
188
-
189
- let airdropInfo: AirdropAuTokenInfo = {
190
- address: address,
191
- exchangeRate: BN.from(exchangeRate),
192
- deploymentBlock: parseInt(deploymentBlock),
193
- underlying: {
194
- minDeposit: BN.from(underlying.minDeposit),
195
- }
196
- }
197
-
198
- this.keepTrackers.push(
199
- new AirdropAuTokenKeepTracker(
200
- networkConnection,
201
- airdropInfo
202
- )
203
- )
204
- }
181
+ // if after the last txn, the balance is still above minDeposit,
182
+ // we should check from the last timestamp to "now"
183
+ if (flag == ABOVE) {
184
+ const timestamp = Math.min(
185
+ settings.airdropEndTimestamp,
186
+ getCurrentTimestamp()
187
+ );
188
+ return (
189
+ timestamp - lastEligibleBalanceTimestamp >= settings.airdropThreshold
190
+ );
205
191
  }
206
192
 
207
- public countWhitelistedAddresses(): number {
208
- return this._whitelistedAddresses.size;
209
- }
193
+ return false;
194
+ }
195
+ }
210
196
 
211
- public isWhitelisted(user: string): boolean {
212
- return this._whitelistedAddresses.has(user.toLocaleLowerCase());
197
+ export class AirdropRead extends BlockchainEntityRead {
198
+ protected _airDrop: AuriAirdrop;
199
+ private _whitelistedAddresses: Set<string>;
200
+ private keepTrackers: AirdropAuTokenKeepTracker[] = [];
201
+ public constructor(networkConnection: NetworkConnection) {
202
+ super(networkConnection);
203
+ this._airDrop = new Contract(
204
+ networkAddresses.misc.AURI_AIRDROP,
205
+ AuriAirdropABI.abi,
206
+ networkConnection.provider
207
+ ) as AuriAirdrop;
208
+
209
+ this._whitelistedAddresses = new Set(
210
+ (AIRDROP_WHITELIST_ADDRESSES as string[]).map((e) =>
211
+ e.toLocaleLowerCase()
212
+ )
213
+ );
214
+
215
+ let auTokens: any = AIRDROP_AUTOKEN_INFO;
216
+
217
+ for (let auToken in auTokens) {
218
+ let { address, exchangeRate, deploymentBlock, underlying } =
219
+ auTokens[auToken];
220
+
221
+ let airdropInfo: AirdropAuTokenInfo = {
222
+ address: address,
223
+ exchangeRate: BN.from(exchangeRate),
224
+ deploymentBlock: parseInt(deploymentBlock),
225
+ underlying: {
226
+ minDeposit: BN.from(underlying.minDeposit),
227
+ },
228
+ };
229
+
230
+ this.keepTrackers.push(
231
+ new AirdropAuTokenKeepTracker(networkConnection, airdropInfo)
232
+ );
213
233
  }
234
+ }
214
235
 
215
- public async hasCompletedChallenge(user: string): Promise<boolean> {
216
- const settings = await AirdropSettings.getSettings(this._networkConnection.provider);
236
+ public countWhitelistedAddresses(): number {
237
+ return this._whitelistedAddresses.size;
238
+ }
217
239
 
218
- if (getCurrentTimestamp() < settings.airdropStartTimestamp) {
219
- return false;
220
- }
240
+ public isWhitelisted(user: string): boolean {
241
+ return this._whitelistedAddresses.has(user.toLocaleLowerCase());
242
+ }
221
243
 
222
- if (!this.isWhitelisted(user)) {
223
- return false;
224
- }
244
+ public async hasCompletedChallenge(user: string): Promise<boolean> {
245
+ const settings = await AirdropSettings.getSettings(
246
+ this._networkConnection.provider
247
+ );
225
248
 
226
- // iterate for all the market and check if the user has completed the challenge
227
- return (await Promise.all(this.keepTrackers.map(async (keepTracker) => {
228
- return keepTracker.isEligible(user);
229
- }))).includes(true);
249
+ if (getCurrentTimestamp() < settings.airdropStartTimestamp) {
250
+ return false;
230
251
  }
231
252
 
232
- /**
233
- * Get redeemable rewards amount of user
234
- */
235
- public async getRedeemableReward(campaign: string, token: Address, user: Address): Promise<TokenAmount> {
236
- let tokenInstance: Token = new Token(
237
- token,
238
- getDecimal(token),
239
- );
240
-
241
- let rewards: BN = await this._airDrop.getRedeemableReward(
242
- utils.formatBytes32String(campaign),
243
- token,
244
- user
245
- )
246
-
247
- return new TokenAmount(tokenInstance, rewards.toString());
253
+ if (!this.isWhitelisted(user)) {
254
+ return false;
248
255
  }
256
+
257
+ // iterate for all the market and check if the user has completed the challenge
258
+ return (
259
+ await Promise.all(
260
+ this.keepTrackers.map(async (keepTracker) => {
261
+ return keepTracker.isEligible(user);
262
+ })
263
+ )
264
+ ).includes(true);
265
+ }
266
+
267
+ /**
268
+ * Get redeemable rewards amount of user
269
+ */
270
+ public async getRedeemableReward(
271
+ campaign: string,
272
+ token: Address,
273
+ user: Address
274
+ ): Promise<TokenAmount> {
275
+ let tokenInstance: Token = new Token(token, getDecimal(token));
276
+
277
+ let rewards: BN = await this._airDrop.getRedeemableReward(
278
+ utils.formatBytes32String(campaign),
279
+ token,
280
+ user
281
+ );
282
+
283
+ return new TokenAmount(tokenInstance, rewards.toString());
284
+ }
249
285
  }
250
286
 
251
287
  export class AirdropReadWrite extends AirdropRead {
252
- /**
253
- * Transfer rewards from multiple campaigns to msg.sender
254
- */
255
- public async redeemMultiple(campaigns: string[], tokens: Address[]): Promise<TransactionResponse> {
256
- assert(campaigns.length == tokens.length, "campaigns and tokens must have the same length");
257
- return this._airDrop.connect(this._networkConnection.signer!).redeem(
258
- campaigns.map(e => utils.formatBytes32String(e)),
259
- tokens,
260
- await this._networkConnection.signer!.getAddress(),
261
- );
262
- }
263
-
264
- /**
265
- * Redeem reward from a single campaign
266
- */
267
- public async redeemSingle(campaign: string, token: Address): Promise<TransactionResponse> {
268
- return this.redeemMultiple([campaign], [token]);
269
- }
288
+ /**
289
+ * Transfer rewards from multiple campaigns to msg.sender
290
+ */
291
+ public async redeemMultiple(
292
+ campaigns: string[],
293
+ tokens: Address[]
294
+ ): Promise<TransactionResponse> {
295
+ assert(
296
+ campaigns.length == tokens.length,
297
+ 'campaigns and tokens must have the same length'
298
+ );
299
+ return this._airDrop.connect(this._networkConnection.signer!).redeem(
300
+ campaigns.map((e) => utils.formatBytes32String(e)),
301
+ tokens,
302
+ await this._networkConnection.signer!.getAddress()
303
+ );
304
+ }
305
+
306
+ /**
307
+ * Redeem reward from a single campaign
308
+ */
309
+ public async redeemSingle(
310
+ campaign: string,
311
+ token: Address
312
+ ): Promise<TransactionResponse> {
313
+ return this.redeemMultiple([campaign], [token]);
314
+ }
270
315
  }
271
316
 
272
317
  export class Airdrop extends BlockchainEntity {
273
- constructor() {
274
- super();
275
- }
276
- public read(networkConnection: NetworkConnection): AirdropRead {
277
- return new AirdropRead(networkConnection);
278
- }
279
- public readWrite(networkConnection: NetworkConnection): AirdropReadWrite {
280
- return new AirdropReadWrite(networkConnection);
281
- }
318
+ constructor() {
319
+ super();
320
+ }
321
+ public read(networkConnection: NetworkConnection): AirdropRead {
322
+ return new AirdropRead(networkConnection);
323
+ }
324
+ public readWrite(networkConnection: NetworkConnection): AirdropReadWrite {
325
+ return new AirdropReadWrite(networkConnection);
326
+ }
282
327
  }
@@ -3,13 +3,18 @@ import axios from 'axios';
3
3
  const AURORA_API_BASE_URL = 'https://api.aurorascan.dev/api';
4
4
 
5
5
  export async function getQuery(
6
- module: string, action: string, params: Record<string, any> = {},
6
+ module: string,
7
+ action: string,
8
+ params: Record<string, any> = {}
7
9
  ): Promise<any> {
8
- params = {...params, 'module': module, 'action': action};
10
+ params = { ...params, module: module, action: action };
9
11
 
10
- let resp = await axios.get(AURORA_API_BASE_URL + '?' + new URLSearchParams(params), {
11
- headers: { 'Content-Type': 'application/json' }
12
- });
12
+ let resp = await axios.get(
13
+ AURORA_API_BASE_URL + '?' + new URLSearchParams(params),
14
+ {
15
+ headers: { 'Content-Type': 'application/json' },
16
+ }
17
+ );
13
18
 
14
- return resp.data.result!;
19
+ return resp.data.result!;
15
20
  }