@gala-chain/launchpad 1.0.1 → 1.0.3

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.
Files changed (110) hide show
  1. package/lib/package.json +2 -2
  2. package/lib/src/api/types/LaunchpadBatchSubmitAuthorities.d.ts +12 -0
  3. package/lib/src/api/types/LaunchpadBatchSubmitAuthorities.d.ts.map +1 -0
  4. package/lib/src/api/types/LaunchpadBatchSubmitAuthorities.js +56 -0
  5. package/lib/src/api/types/LaunchpadBatchSubmitAuthorities.js.map +1 -0
  6. package/lib/src/api/types/LaunchpadDtos.d.ts +14 -0
  7. package/lib/src/api/types/LaunchpadDtos.d.ts.map +1 -1
  8. package/lib/src/api/types/LaunchpadDtos.js +45 -1
  9. package/lib/src/api/types/LaunchpadDtos.js.map +1 -1
  10. package/lib/src/api/types/LaunchpadFeeConfig.d.ts +3 -2
  11. package/lib/src/api/types/LaunchpadFeeConfig.d.ts.map +1 -1
  12. package/lib/src/api/types/LaunchpadFeeConfig.js +15 -6
  13. package/lib/src/api/types/LaunchpadFeeConfig.js.map +1 -1
  14. package/lib/src/api/types/LaunchpadFinalizeAllocation.js +1 -2
  15. package/lib/src/api/types/LaunchpadFinalizeAllocation.js.map +1 -1
  16. package/lib/src/api/types/LaunchpadSale.js +1 -2
  17. package/lib/src/api/types/LaunchpadSale.js.map +1 -1
  18. package/lib/src/api/types/index.d.ts +1 -0
  19. package/lib/src/api/types/index.d.ts.map +1 -1
  20. package/lib/src/api/types/index.js +1 -0
  21. package/lib/src/api/types/index.js.map +1 -1
  22. package/lib/src/api/validators/decorators.js.map +1 -1
  23. package/lib/src/chaincode/LaunchpadContract.d.ts +6 -1
  24. package/lib/src/chaincode/LaunchpadContract.d.ts.map +1 -1
  25. package/lib/src/chaincode/LaunchpadContract.js +97 -0
  26. package/lib/src/chaincode/LaunchpadContract.js.map +1 -1
  27. package/lib/src/chaincode/launchpad/buyExactToken.d.ts.map +1 -1
  28. package/lib/src/chaincode/launchpad/buyExactToken.js +22 -9
  29. package/lib/src/chaincode/launchpad/buyExactToken.js.map +1 -1
  30. package/lib/src/chaincode/launchpad/buyWithNative.d.ts.map +1 -1
  31. package/lib/src/chaincode/launchpad/buyWithNative.js +31 -9
  32. package/lib/src/chaincode/launchpad/buyWithNative.js.map +1 -1
  33. package/lib/src/chaincode/launchpad/callMemeTokenIn.d.ts +1 -0
  34. package/lib/src/chaincode/launchpad/callMemeTokenIn.d.ts.map +1 -1
  35. package/lib/src/chaincode/launchpad/callMemeTokenIn.js +3 -5
  36. package/lib/src/chaincode/launchpad/callMemeTokenIn.js.map +1 -1
  37. package/lib/src/chaincode/launchpad/callMemeTokenOut.d.ts +1 -0
  38. package/lib/src/chaincode/launchpad/callMemeTokenOut.d.ts.map +1 -1
  39. package/lib/src/chaincode/launchpad/callMemeTokenOut.js +5 -5
  40. package/lib/src/chaincode/launchpad/callMemeTokenOut.js.map +1 -1
  41. package/lib/src/chaincode/launchpad/callNativeTokenIn.d.ts +1 -0
  42. package/lib/src/chaincode/launchpad/callNativeTokenIn.d.ts.map +1 -1
  43. package/lib/src/chaincode/launchpad/callNativeTokenIn.js +7 -6
  44. package/lib/src/chaincode/launchpad/callNativeTokenIn.js.map +1 -1
  45. package/lib/src/chaincode/launchpad/callNativeTokenOut.d.ts +1 -0
  46. package/lib/src/chaincode/launchpad/callNativeTokenOut.d.ts.map +1 -1
  47. package/lib/src/chaincode/launchpad/callNativeTokenOut.js +4 -5
  48. package/lib/src/chaincode/launchpad/callNativeTokenOut.js.map +1 -1
  49. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.d.ts +12 -0
  50. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.d.ts.map +1 -1
  51. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.js +26 -6
  52. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.js.map +1 -1
  53. package/lib/src/chaincode/launchpad/createSale.d.ts.map +1 -1
  54. package/lib/src/chaincode/launchpad/createSale.js +10 -12
  55. package/lib/src/chaincode/launchpad/createSale.js.map +1 -1
  56. package/lib/src/chaincode/launchpad/fees.d.ts +1 -0
  57. package/lib/src/chaincode/launchpad/fees.d.ts.map +1 -1
  58. package/lib/src/chaincode/launchpad/fees.js +6 -2
  59. package/lib/src/chaincode/launchpad/fees.js.map +1 -1
  60. package/lib/src/chaincode/launchpad/fetchLaunchpadAdressConfig.js.map +1 -1
  61. package/lib/src/chaincode/launchpad/fetchSaleDetails.d.ts.map +1 -1
  62. package/lib/src/chaincode/launchpad/fetchSaleDetails.js +0 -4
  63. package/lib/src/chaincode/launchpad/fetchSaleDetails.js.map +1 -1
  64. package/lib/src/chaincode/launchpad/finaliseSale.js +3 -3
  65. package/lib/src/chaincode/launchpad/finaliseSale.js.map +1 -1
  66. package/lib/src/chaincode/launchpad/finalizeTokenAllocation.js.map +1 -1
  67. package/lib/src/chaincode/launchpad/index.d.ts +1 -0
  68. package/lib/src/chaincode/launchpad/index.d.ts.map +1 -1
  69. package/lib/src/chaincode/launchpad/index.js +1 -0
  70. package/lib/src/chaincode/launchpad/index.js.map +1 -1
  71. package/lib/src/chaincode/launchpad/launchpadBatchSubmitAuthorizations.d.ts +24 -0
  72. package/lib/src/chaincode/launchpad/launchpadBatchSubmitAuthorizations.d.ts.map +1 -0
  73. package/lib/src/chaincode/launchpad/launchpadBatchSubmitAuthorizations.js +84 -0
  74. package/lib/src/chaincode/launchpad/launchpadBatchSubmitAuthorizations.js.map +1 -0
  75. package/lib/src/chaincode/launchpad/preMintCalculation.d.ts.map +1 -1
  76. package/lib/src/chaincode/launchpad/preMintCalculation.js +0 -4
  77. package/lib/src/chaincode/launchpad/preMintCalculation.js.map +1 -1
  78. package/lib/src/chaincode/launchpad/sellExactToken.d.ts.map +1 -1
  79. package/lib/src/chaincode/launchpad/sellExactToken.js +27 -11
  80. package/lib/src/chaincode/launchpad/sellExactToken.js.map +1 -1
  81. package/lib/src/chaincode/launchpad/sellWithNative.d.ts.map +1 -1
  82. package/lib/src/chaincode/launchpad/sellWithNative.js +30 -8
  83. package/lib/src/chaincode/launchpad/sellWithNative.js.map +1 -1
  84. package/lib/src/chaincode/utils/launchpadSaleUtils.js +2 -2
  85. package/lib/src/chaincode/utils/launchpadSaleUtils.js.map +1 -1
  86. package/lib/src/cli.js.map +1 -1
  87. package/lib/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +3 -3
  89. package/src/api/types/LaunchpadBatchSubmitAuthorities.ts +53 -0
  90. package/src/api/types/LaunchpadDtos.ts +38 -0
  91. package/src/api/types/LaunchpadFeeConfig.ts +13 -4
  92. package/src/api/types/index.ts +1 -0
  93. package/src/chaincode/LaunchpadContract.ts +104 -1
  94. package/src/chaincode/launchpad/buyExactToken.ts +18 -6
  95. package/src/chaincode/launchpad/buyWithNative.ts +29 -6
  96. package/src/chaincode/launchpad/callMemeTokenIn.ts +9 -8
  97. package/src/chaincode/launchpad/callMemeTokenOut.ts +9 -7
  98. package/src/chaincode/launchpad/callNativeTokenIn.ts +11 -8
  99. package/src/chaincode/launchpad/callNativeTokenOut.ts +9 -8
  100. package/src/chaincode/launchpad/configureLaunchpadFeeConfig.ts +27 -4
  101. package/src/chaincode/launchpad/createSale.ts +1 -5
  102. package/src/chaincode/launchpad/fees.ts +5 -1
  103. package/src/chaincode/launchpad/fetchSaleDetails.ts +0 -5
  104. package/src/chaincode/launchpad/finaliseSale.ts +3 -3
  105. package/src/chaincode/launchpad/index.ts +1 -0
  106. package/src/chaincode/launchpad/launchpadBatchSubmitAuthorizations.spec.ts +185 -0
  107. package/src/chaincode/launchpad/launchpadBatchSubmitAuthorizations.ts +105 -0
  108. package/src/chaincode/launchpad/preMintCalculation.ts +0 -5
  109. package/src/chaincode/launchpad/sellExactToken.ts +30 -15
  110. package/src/chaincode/launchpad/sellWithNative.ts +31 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gala-chain/launchpad",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "GalaChain Launchpad Chaincode",
5
5
  "main": "lib/src/index.js",
6
6
  "types": "lib/src/index.d.ts",
@@ -49,6 +49,6 @@
49
49
  "prettier": "^3.1.1",
50
50
  "ts-jest": "^29.1.2",
51
51
  "ts-node": "^10.9.1",
52
- "typescript": "^5.3.3"
52
+ "typescript": "^5.1.6"
53
53
  }
54
- }
54
+ }
@@ -0,0 +1,53 @@
1
+ /*
2
+ * Copyright (c) Gala Games Inc. All rights reserved.
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+ import { ChainObject } from "@gala-chain/api";
16
+ import { Exclude } from "class-transformer";
17
+ import { ArrayNotEmpty, IsString } from "class-validator";
18
+
19
+ export class LaunchpadBatchSubmitAuthorities extends ChainObject {
20
+ @Exclude()
21
+ public static INDEX_KEY = "GCLBSA"; // GalaChain Launchpad Batch Submit Authorities
22
+
23
+ @ArrayNotEmpty()
24
+ @IsString({ each: true })
25
+ authorities: string[];
26
+
27
+ constructor(authorities: string[]) {
28
+ super();
29
+ this.authorities = authorities;
30
+ }
31
+
32
+ public addOrUpdateAuthorities(newAuthorities: string[]) {
33
+ this.authorities = newAuthorities;
34
+ }
35
+
36
+ public addAuthority(authority: string) {
37
+ if (!this.authorities.includes(authority)) {
38
+ this.authorities.push(authority);
39
+ }
40
+ }
41
+
42
+ public removeAuthority(authority: string) {
43
+ this.authorities = this.authorities.filter((auth) => auth !== authority);
44
+ }
45
+
46
+ public isAuthorized(authority: string): boolean {
47
+ return this.authorities.includes(authority);
48
+ }
49
+
50
+ public getAuthorities(): string[] {
51
+ return [...this.authorities];
52
+ }
53
+ }
@@ -24,6 +24,8 @@ import {
24
24
  import BigNumber from "bignumber.js";
25
25
  import { Type } from "class-transformer";
26
26
  import {
27
+ ArrayNotEmpty,
28
+ IsArray,
27
29
  IsBoolean,
28
30
  IsNotEmpty,
29
31
  IsNumber,
@@ -275,6 +277,9 @@ export class TradeResDto {
275
277
  @IsNotEmpty()
276
278
  public inputQuantity: string;
277
279
 
280
+ @IsNotEmpty()
281
+ public totalFees: string;
282
+
278
283
  @IsNotEmpty()
279
284
  public outputQuantity: string;
280
285
 
@@ -328,6 +333,12 @@ export class ConfigureLaunchpadFeeAddressDto extends SubmitCallDTO {
328
333
  @IsUserAlias()
329
334
  public newPlatformFeeAddress?: UserAlias;
330
335
 
336
+ @IsOptional()
337
+ @IsNumber()
338
+ @Min(0)
339
+ @Max(1)
340
+ public newFeeAmount?: number;
341
+
331
342
  @IsOptional()
332
343
  @IsUserAlias({ each: true })
333
344
  public newAuthorities?: UserAlias[];
@@ -355,6 +366,10 @@ export class TradeCalculationResFeesDto {
355
366
  @IsNotEmpty()
356
367
  @IsString()
357
368
  reverseBondingCurve: string;
369
+
370
+ @IsNotEmpty()
371
+ @IsString()
372
+ transactionFees: string;
358
373
  }
359
374
 
360
375
  export class TradeCalculationResDto {
@@ -366,3 +381,26 @@ export class TradeCalculationResDto {
366
381
  @Type(() => TradeCalculationResFeesDto)
367
382
  public extraFees: TradeCalculationResFeesDto;
368
383
  }
384
+
385
+ export class AuthorizeBatchSubmitterDto extends SubmitCallDTO {
386
+ @IsArray()
387
+ @ArrayNotEmpty()
388
+ @IsString({ each: true })
389
+ authorities: string[];
390
+ }
391
+
392
+ export class DeauthorizeBatchSubmitterDto extends SubmitCallDTO {
393
+ @IsString()
394
+ authority: string;
395
+ }
396
+
397
+ export class FetchBatchSubmitAuthoritiesDto extends ChainCallDTO {
398
+ // No additional fields needed for fetching all authorities
399
+ }
400
+
401
+ export class BatchSubmitAuthoritiesResDto extends ChainCallDTO {
402
+ @IsArray()
403
+ @ArrayNotEmpty()
404
+ @IsString({ each: true })
405
+ authorities: string[];
406
+ }
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import { ChainObject, IsUserAlias, UserAlias } from "@gala-chain/api";
16
16
  import { Exclude } from "class-transformer";
17
- import { ArrayNotEmpty, IsNotEmpty } from "class-validator";
17
+ import { ArrayNotEmpty, IsNotEmpty, IsNumber, Max, Min } from "class-validator";
18
18
  import { JSONSchema } from "class-validator-jsonschema";
19
19
 
20
20
  @JSONSchema({
@@ -22,24 +22,33 @@ import { JSONSchema } from "class-validator-jsonschema";
22
22
  })
23
23
  export class LaunchpadFeeConfig extends ChainObject {
24
24
  @Exclude()
25
- public static INDEX_KEY = "GCLFC"; // GalaChain Launchpad Fee Configuration
25
+ public static INDEX_KEY = "GCLPFC"; // GalaChain Launchpad Fee Configuration
26
26
 
27
27
  @IsNotEmpty()
28
28
  @IsUserAlias()
29
29
  feeAddress: UserAlias;
30
30
 
31
+ @IsNotEmpty()
32
+ @IsNumber()
33
+ @Min(0)
34
+ @Max(1)
35
+ public feeAmount: number;
36
+
31
37
  @ArrayNotEmpty()
32
38
  @IsUserAlias({ each: true })
33
39
  authorities: UserAlias[];
34
40
 
35
- constructor(feeAddress: UserAlias, authorities: UserAlias[]) {
41
+ constructor(feeAddress: UserAlias, feeAmount: number, authorities: UserAlias[]) {
36
42
  super();
37
43
  this.feeAddress = feeAddress;
44
+ this.feeAmount = feeAmount;
38
45
  this.authorities = authorities;
39
46
  }
40
47
 
41
- public setNewFeeAddress(newfeeAddress: UserAlias, newAuthorities: UserAlias[]) {
48
+ public updateFeeConfig(newfeeAddress: UserAlias, newFeeAmount: number, newAuthorities: UserAlias[]) {
42
49
  this.feeAddress = newfeeAddress;
50
+ this.feeAmount = newFeeAmount;
43
51
  this.authorities = newAuthorities;
52
+ this.validate();
44
53
  }
45
54
  }
@@ -17,3 +17,4 @@ export * from "./LaunchpadDtos";
17
17
  export * from "./LaunchpadFinalizeAllocation";
18
18
  export * from "./LaunchpadFeeConfig";
19
19
  export * from "./LaunchpadSale";
20
+ export * from "./LaunchpadBatchSubmitAuthorities";
@@ -12,21 +12,29 @@
12
12
  * See the License for the specific language governing permissions and
13
13
  * limitations under the License.
14
14
  */
15
+ import { BatchDto, GalaChainResponse, UnauthorizedError } from "@gala-chain/api";
15
16
  import {
17
+ BatchWriteLimitExceededError,
16
18
  EVALUATE,
17
19
  Evaluate,
18
20
  GalaChainContext,
19
21
  GalaContract,
20
22
  GalaTransaction,
21
- Submit
23
+ SUBMIT,
24
+ Submit,
25
+ getApiMethod
22
26
  } from "@gala-chain/chaincode";
23
27
 
24
28
  import { version } from "../../package.json";
25
29
  import {
30
+ AuthorizeBatchSubmitterDto,
31
+ BatchSubmitAuthoritiesResDto,
26
32
  ConfigureLaunchpadFeeAddressDto,
27
33
  CreateSaleResDto,
28
34
  CreateTokenSaleDTO,
35
+ DeauthorizeBatchSubmitterDto,
29
36
  ExactTokenQuantityDto,
37
+ FetchBatchSubmitAuthoritiesDto,
30
38
  FetchSaleDto,
31
39
  FinalizeTokenAllocationDto,
32
40
  LaunchpadFeeConfig,
@@ -45,6 +53,7 @@ import {
45
53
  sellWithNativeFeeGate
46
54
  } from "./dexLaunchpadFeeGate";
47
55
  import {
56
+ authorizeLaunchpadBatchSubmitter,
48
57
  buyExactToken,
49
58
  buyWithNative,
50
59
  calculatePreMintTokens,
@@ -54,9 +63,12 @@ import {
54
63
  callNativeTokenOut,
55
64
  configureLaunchpadFeeAddress,
56
65
  createSale,
66
+ deauthorizeLaunchpadBatchSubmitter,
67
+ fetchLaunchpadBatchSubmitAuthorities,
57
68
  fetchLaunchpadFeeConfig,
58
69
  fetchSaleDetails,
59
70
  finalizeTokenAllocation,
71
+ getLaunchpadBatchSubmitAuthorities,
60
72
  sellExactToken,
61
73
  sellWithNative
62
74
  } from "./launchpad";
@@ -208,4 +220,95 @@ export class LaunchpadContract extends GalaContract {
208
220
  public async FetchLaunchpadFeeConfig(ctx: GalaChainContext): Promise<LaunchpadFeeConfig> {
209
221
  return fetchLaunchpadFeeConfig(ctx);
210
222
  }
223
+
224
+ @GalaTransaction({
225
+ type: SUBMIT,
226
+ in: BatchDto,
227
+ out: "object",
228
+ description: "Submit a batch of transactions",
229
+ verifySignature: true
230
+ })
231
+ public async BatchSubmit(ctx: GalaChainContext, batchDto: BatchDto): Promise<GalaChainResponse<unknown>[]> {
232
+ // Check if the calling user is authorized to submit batches
233
+ const batchAuthorities = await fetchLaunchpadBatchSubmitAuthorities(ctx);
234
+ if (!batchAuthorities.isAuthorized(ctx.callingUser)) {
235
+ throw new UnauthorizedError(
236
+ `CallingUser ${ctx.callingUser} is not authorized to submit batches. ` +
237
+ `Authorized users: ${batchAuthorities.getAuthorities().join(", ")}`
238
+ );
239
+ }
240
+
241
+ const responses: GalaChainResponse<unknown>[] = [];
242
+
243
+ const softWritesLimit = batchDto.writesLimit ?? BatchDto.WRITES_DEFAULT_LIMIT;
244
+ const writesLimit = Math.min(softWritesLimit, BatchDto.WRITES_HARD_LIMIT);
245
+ let writesCount = ctx.stub.getWritesCount();
246
+
247
+ for (const [index, op] of batchDto.operations.entries()) {
248
+ // Use sandboxed context to avoid flushes of writes and deletes, and populate
249
+ // the stub with current writes and deletes.
250
+ const sandboxCtx = ctx.createReadOnlyContext(index);
251
+ sandboxCtx.stub.setWrites(ctx.stub.getWrites());
252
+ sandboxCtx.stub.setDeletes(ctx.stub.getDeletes());
253
+
254
+ // Execute the operation. Collect both successful and failed responses.
255
+ let response: GalaChainResponse<unknown>;
256
+ try {
257
+ if (writesCount >= writesLimit) {
258
+ throw new BatchWriteLimitExceededError(writesLimit);
259
+ }
260
+
261
+ const method = getApiMethod(this, op.method, (m) => m.isWrite && m.methodName !== "BatchSubmit");
262
+ response = await this[method.methodName](sandboxCtx, op.dto);
263
+ } catch (error) {
264
+ response = GalaChainResponse.Error(error);
265
+ }
266
+ responses.push(response);
267
+
268
+ // Update the current context with the writes and deletes if the operation
269
+ // is successful.
270
+ if (GalaChainResponse.isSuccess(response)) {
271
+ ctx.stub.setWrites(sandboxCtx.stub.getWrites());
272
+ ctx.stub.setDeletes(sandboxCtx.stub.getDeletes());
273
+ writesCount = ctx.stub.getWritesCount();
274
+ }
275
+ }
276
+ return responses;
277
+ }
278
+
279
+ @Submit({
280
+ in: AuthorizeBatchSubmitterDto,
281
+ out: BatchSubmitAuthoritiesResDto,
282
+ allowedOrgs: [process.env.CURATOR_ORG_MSP ?? "CuratorOrg"]
283
+ })
284
+ public async AuthorizeBatchSubmitter(
285
+ ctx: GalaChainContext,
286
+ dto: AuthorizeBatchSubmitterDto
287
+ ): Promise<BatchSubmitAuthoritiesResDto> {
288
+ return await authorizeLaunchpadBatchSubmitter(ctx, dto);
289
+ }
290
+
291
+ @Submit({
292
+ in: DeauthorizeBatchSubmitterDto,
293
+ out: BatchSubmitAuthoritiesResDto,
294
+ allowedOrgs: [process.env.CURATOR_ORG_MSP ?? "CuratorOrg"]
295
+ })
296
+ public async DeauthorizeBatchSubmitter(
297
+ ctx: GalaChainContext,
298
+ dto: DeauthorizeBatchSubmitterDto
299
+ ): Promise<BatchSubmitAuthoritiesResDto> {
300
+ return await deauthorizeLaunchpadBatchSubmitter(ctx, dto);
301
+ }
302
+
303
+ @GalaTransaction({
304
+ type: EVALUATE,
305
+ in: FetchBatchSubmitAuthoritiesDto,
306
+ out: BatchSubmitAuthoritiesResDto
307
+ })
308
+ public async GetBatchSubmitAuthorities(
309
+ ctx: GalaChainContext,
310
+ dto: FetchBatchSubmitAuthoritiesDto
311
+ ): Promise<BatchSubmitAuthoritiesResDto> {
312
+ return await getLaunchpadBatchSubmitAuthorities(ctx, dto);
313
+ }
211
314
  }
@@ -13,18 +13,14 @@
13
13
  * limitations under the License.
14
14
  */
15
15
  import { GalaChainContext, fetchTokenClass, putChainObject, transferToken } from "@gala-chain/chaincode";
16
- import { BigNumber } from "bignumber.js";
16
+ import BigNumber from "bignumber.js";
17
17
 
18
18
  import { ExactTokenQuantityDto, LaunchpadSale, TradeResDto } from "../../api/types";
19
19
  import { SlippageToleranceExceededError } from "../../api/utils/error";
20
- import { fetchAndValidateSale } from "../utils";
20
+ import { fetchAndValidateSale, fetchLaunchpadFeeAddress } from "../utils";
21
21
  import { callNativeTokenIn } from "./callNativeTokenIn";
22
22
  import { finalizeSale } from "./finaliseSale";
23
23
 
24
- BigNumber.config({
25
- ROUNDING_MODE: BigNumber.ROUND_UP
26
- });
27
-
28
24
  /**
29
25
  * Executes the purchase of an exact amount of tokens in a token sale.
30
26
  *
@@ -53,6 +49,7 @@ export async function buyExactToken(
53
49
 
54
50
  // Calculate the required amount of native tokens to buy the specified token amount
55
51
  const callNativeTokenInResult1 = await callNativeTokenIn(ctx, buyTokenDTO);
52
+ let transactionFees = callNativeTokenInResult1.extraFees.transactionFees;
56
53
  let nativeTokensToBuy = new BigNumber(callNativeTokenInResult1.calculatedQuantity);
57
54
  const nativeToken = sale.fetchNativeTokenInstanceKey();
58
55
  const memeToken = sale.fetchSellingTokenInstanceKey();
@@ -62,6 +59,7 @@ export async function buyExactToken(
62
59
  buyTokenDTO.tokenQuantity = tokenLeftInVault;
63
60
  const callNativeTokenInResult2 = await callNativeTokenIn(ctx, buyTokenDTO);
64
61
  nativeTokensToBuy = new BigNumber(callNativeTokenInResult2.calculatedQuantity);
62
+ transactionFees = callNativeTokenInResult2.extraFees.transactionFees;
65
63
  isSaleFinalized = true;
66
64
  }
67
65
 
@@ -81,6 +79,19 @@ export async function buyExactToken(
81
79
  );
82
80
  }
83
81
 
82
+ // Transfer transaction fees
83
+ const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
84
+ if (launchpadFeeAddressConfiguration && transactionFees) {
85
+ await transferToken(ctx, {
86
+ from: ctx.callingUser,
87
+ to: launchpadFeeAddressConfiguration.feeAddress,
88
+ tokenInstanceKey: nativeToken,
89
+ quantity: new BigNumber(transactionFees),
90
+ allowancesToUse: [],
91
+ authorizedOnBehalf: undefined
92
+ });
93
+ }
94
+
84
95
  // Transfer native tokens from the buyer to the vault
85
96
  await transferToken(ctx, {
86
97
  from: ctx.callingUser,
@@ -117,6 +128,7 @@ export async function buyExactToken(
117
128
  const token = await fetchTokenClass(ctx, sale.sellingToken);
118
129
  return {
119
130
  inputQuantity: nativeTokensToBuy.toFixed(),
131
+ totalFees: transactionFees,
120
132
  outputQuantity: buyTokenDTO.tokenQuantity.toFixed(),
121
133
  tokenName: token.name,
122
134
  tradeType: "Buy",
@@ -13,19 +13,15 @@
13
13
  * limitations under the License.
14
14
  */
15
15
  import { GalaChainContext, fetchTokenClass, putChainObject, transferToken } from "@gala-chain/chaincode";
16
- import { BigNumber } from "bignumber.js";
16
+ import BigNumber from "bignumber.js";
17
17
 
18
18
  import { ExactTokenQuantityDto, LaunchpadSale, NativeTokenQuantityDto, TradeResDto } from "../../api/types";
19
19
  import { SlippageToleranceExceededError } from "../../api/utils/error";
20
- import { fetchAndValidateSale } from "../utils";
20
+ import { fetchAndValidateSale, fetchLaunchpadFeeAddress } from "../utils";
21
21
  import { callMemeTokenOut } from "./callMemeTokenOut";
22
22
  import { callNativeTokenIn } from "./callNativeTokenIn";
23
23
  import { finalizeSale } from "./finaliseSale";
24
24
 
25
- BigNumber.config({
26
- ROUNDING_MODE: BigNumber.ROUND_UP
27
- });
28
-
29
25
  /**
30
26
  * Executes the purchase of tokens using a specified amount of native tokens.
31
27
  *
@@ -49,22 +45,30 @@ export async function buyWithNative(
49
45
  buyTokenDTO: NativeTokenQuantityDto
50
46
  ): Promise<TradeResDto> {
51
47
  let isSaleFinalized = false;
48
+
49
+ // Fetch and validate sale state
52
50
  const sale = await fetchAndValidateSale(ctx, buyTokenDTO.vaultAddress);
53
51
  const tokensLeftInVault = new BigNumber(sale.sellingTokenQuantity);
52
+
53
+ // Calculate how many tokens the user can buy and fee info
54
54
  const callMemeTokenOutResult = await callMemeTokenOut(ctx, buyTokenDTO);
55
+ let transactionFees = callMemeTokenOutResult.extraFees.transactionFees;
55
56
  let tokensToBuy = new BigNumber(callMemeTokenOutResult.calculatedQuantity);
56
57
 
57
58
  const nativeToken = sale.fetchNativeTokenInstanceKey();
58
59
  const memeToken = sale.fetchSellingTokenInstanceKey();
59
60
 
61
+ // If vault has fewer tokens than what user wants to buy, cap the purchase
60
62
  if (tokensLeftInVault.comparedTo(tokensToBuy) <= 0) {
61
63
  tokensToBuy = tokensLeftInVault;
62
64
  const nativeTokensrequiredToBuyDto = new ExactTokenQuantityDto(buyTokenDTO.vaultAddress, tokensToBuy);
63
65
  const callNativeTokenInResult = await callNativeTokenIn(ctx, nativeTokensrequiredToBuyDto);
66
+ transactionFees = callMemeTokenOutResult.extraFees.transactionFees;
64
67
  buyTokenDTO.nativeTokenQuantity = new BigNumber(callNativeTokenInResult.calculatedQuantity);
65
68
  isSaleFinalized = true;
66
69
  }
67
70
 
71
+ // Finalize sale if market cap is reached
68
72
  if (
69
73
  buyTokenDTO.nativeTokenQuantity
70
74
  .plus(new BigNumber(sale.nativeTokenQuantity))
@@ -72,12 +76,27 @@ export async function buyWithNative(
72
76
  )
73
77
  isSaleFinalized = true;
74
78
 
79
+ // Check for slippage condition
75
80
  if (buyTokenDTO.expectedToken && buyTokenDTO.expectedToken.comparedTo(tokensToBuy) > 0) {
76
81
  throw new SlippageToleranceExceededError(
77
82
  "Tokens expected from this operation are more than the the actual amount that will be provided."
78
83
  );
79
84
  }
80
85
 
86
+ // Transfer transaction fees to launchpad fee address
87
+ const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
88
+ if (launchpadFeeAddressConfiguration && transactionFees) {
89
+ await transferToken(ctx, {
90
+ from: ctx.callingUser,
91
+ to: launchpadFeeAddressConfiguration.feeAddress,
92
+ tokenInstanceKey: nativeToken,
93
+ quantity: new BigNumber(transactionFees),
94
+ allowancesToUse: [],
95
+ authorizedOnBehalf: undefined
96
+ });
97
+ }
98
+
99
+ // Transfer native tokens from buyer to vault
81
100
  await transferToken(ctx, {
82
101
  from: ctx.callingUser,
83
102
  to: buyTokenDTO.vaultAddress,
@@ -87,6 +106,7 @@ export async function buyWithNative(
87
106
  authorizedOnBehalf: undefined
88
107
  });
89
108
 
109
+ // Transfer meme tokens from vault to buyer
90
110
  await transferToken(ctx, {
91
111
  from: buyTokenDTO.vaultAddress,
92
112
  to: ctx.callingUser,
@@ -99,9 +119,11 @@ export async function buyWithNative(
99
119
  }
100
120
  });
101
121
 
122
+ // Update sale object with purchase data
102
123
  sale.buyToken(tokensToBuy, buyTokenDTO.nativeTokenQuantity);
103
124
  await putChainObject(ctx, sale);
104
125
 
126
+ // Finalize sale if it's complete
105
127
  if (isSaleFinalized) {
106
128
  await finalizeSale(ctx, sale);
107
129
  }
@@ -109,6 +131,7 @@ export async function buyWithNative(
109
131
  const token = await fetchTokenClass(ctx, sale.sellingToken);
110
132
  return {
111
133
  inputQuantity: buyTokenDTO.nativeTokenQuantity.toFixed(),
134
+ totalFees: transactionFees,
112
135
  outputQuantity: tokensToBuy.toFixed(),
113
136
  tokenName: token.name,
114
137
  tradeType: "Buy",
@@ -14,16 +14,12 @@
14
14
  */
15
15
  import { ValidationFailedError } from "@gala-chain/api";
16
16
  import { GalaChainContext } from "@gala-chain/chaincode";
17
- import { BigNumber } from "bignumber.js";
17
+ import BigNumber from "bignumber.js";
18
18
  import Decimal from "decimal.js";
19
19
 
20
20
  import { LaunchpadSale, NativeTokenQuantityDto } from "../../api/types";
21
- import { fetchAndValidateSale, getBondingConstants } from "../utils";
22
- import { calculateReverseBondingCurveFee } from "./fees";
23
-
24
- BigNumber.config({
25
- ROUNDING_MODE: BigNumber.ROUND_UP
26
- });
21
+ import { fetchAndValidateSale, fetchLaunchpadFeeAddress, getBondingConstants } from "../utils";
22
+ import { calculateReverseBondingCurveFee, calculateTransactionFee } from "./fees";
27
23
 
28
24
  function calculateMemeTokensRequired(sale: LaunchpadSale, requestedNativeTokenQuantity: BigNumber) {
29
25
  const totalTokensSold = new Decimal(sale.fetchTokensSold()); // current tokens sold / x
@@ -72,11 +68,16 @@ function calculateMemeTokensRequired(sale: LaunchpadSale, requestedNativeTokenQu
72
68
  */
73
69
  export async function callMemeTokenIn(ctx: GalaChainContext, sellTokenDTO: NativeTokenQuantityDto) {
74
70
  const sale = await fetchAndValidateSale(ctx, sellTokenDTO.vaultAddress);
71
+ const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
75
72
 
76
73
  return {
77
74
  calculatedQuantity: calculateMemeTokensRequired(sale, sellTokenDTO.nativeTokenQuantity),
78
75
  extraFees: {
79
- reverseBondingCurve: calculateReverseBondingCurveFee(sale, sellTokenDTO.nativeTokenQuantity).toString()
76
+ reverseBondingCurve: calculateReverseBondingCurveFee(sale, sellTokenDTO.nativeTokenQuantity).toString(),
77
+ transactionFees: calculateTransactionFee(
78
+ sellTokenDTO.nativeTokenQuantity,
79
+ launchpadFeeAddressConfiguration?.feeAmount
80
+ )
80
81
  }
81
82
  };
82
83
  }
@@ -13,15 +13,12 @@
13
13
  * limitations under the License.
14
14
  */
15
15
  import { GalaChainContext } from "@gala-chain/chaincode";
16
- import { BigNumber } from "bignumber.js";
16
+ import BigNumber from "bignumber.js";
17
17
  import Decimal from "decimal.js";
18
18
 
19
19
  import { LaunchpadSale, NativeTokenQuantityDto } from "../../api/types";
20
- import { fetchAndValidateSale, getBondingConstants } from "../utils";
21
-
22
- BigNumber.config({
23
- ROUNDING_MODE: BigNumber.ROUND_UP
24
- });
20
+ import { fetchAndValidateSale, fetchLaunchpadFeeAddress, getBondingConstants } from "../utils";
21
+ import { calculateTransactionFee } from "./fees";
25
22
 
26
23
  /**
27
24
  * Calculates the number of tokens that can be purchased using a specified amount
@@ -71,10 +68,15 @@ export async function callMemeTokenOut(ctx: GalaChainContext, buyTokenDTO: Nativ
71
68
  roundedResult = new Decimal("1e+7").minus(new Decimal(totalTokensSold));
72
69
  }
73
70
 
71
+ const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
74
72
  return {
75
73
  calculatedQuantity: roundedResult.toFixed(),
76
74
  extraFees: {
77
- reverseBondingCurve: "0"
75
+ reverseBondingCurve: "0",
76
+ transactionFees: calculateTransactionFee(
77
+ BigNumber(nativeTokens.toFixed()),
78
+ launchpadFeeAddressConfiguration?.feeAmount
79
+ )
78
80
  }
79
81
  };
80
82
  }
@@ -13,15 +13,12 @@
13
13
  * limitations under the License.
14
14
  */
15
15
  import { GalaChainContext } from "@gala-chain/chaincode";
16
- import { BigNumber } from "bignumber.js";
16
+ import BigNumber from "bignumber.js";
17
17
  import Decimal from "decimal.js";
18
18
 
19
19
  import { ExactTokenQuantityDto } from "../../api/types";
20
- import { fetchAndValidateSale, getBondingConstants } from "../utils";
21
-
22
- BigNumber.config({
23
- ROUNDING_MODE: BigNumber.ROUND_UP
24
- });
20
+ import { fetchAndValidateSale, fetchLaunchpadFeeAddress, getBondingConstants } from "../utils";
21
+ import { calculateTransactionFee } from "./fees";
25
22
 
26
23
  /**
27
24
  * Calculates the amount of native tokens required to purchase a specified amount
@@ -62,10 +59,16 @@ export async function callNativeTokenIn(ctx: GalaChainContext, buyTokenDTO: Exac
62
59
 
63
60
  const price = constantFactor.mul(differenceOfExponentials);
64
61
 
62
+ const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
63
+ const roundedPrice = price.toDecimalPlaces(8, Decimal.ROUND_UP).toFixed();
65
64
  return {
66
- calculatedQuantity: price.toDecimalPlaces(8, Decimal.ROUND_UP).toFixed(),
65
+ calculatedQuantity: roundedPrice,
67
66
  extraFees: {
68
- reverseBondingCurve: "0"
67
+ reverseBondingCurve: "0",
68
+ transactionFees: calculateTransactionFee(
69
+ BigNumber(roundedPrice),
70
+ launchpadFeeAddressConfiguration?.feeAmount
71
+ )
69
72
  }
70
73
  };
71
74
  }
@@ -13,16 +13,12 @@
13
13
  * limitations under the License.
14
14
  */
15
15
  import { GalaChainContext } from "@gala-chain/chaincode";
16
- import { BigNumber } from "bignumber.js";
16
+ import BigNumber from "bignumber.js";
17
17
  import Decimal from "decimal.js";
18
18
 
19
19
  import { ExactTokenQuantityDto, LaunchpadSale } from "../../api/types";
20
- import { fetchAndValidateSale, getBondingConstants } from "../utils";
21
- import { calculateReverseBondingCurveFee } from "./fees";
22
-
23
- BigNumber.config({
24
- ROUNDING_MODE: BigNumber.ROUND_UP
25
- });
20
+ import { fetchAndValidateSale, fetchLaunchpadFeeAddress, getBondingConstants } from "../utils";
21
+ import { calculateReverseBondingCurveFee, calculateTransactionFee } from "./fees";
26
22
 
27
23
  function calculateNativeTokensReceived(sale: LaunchpadSale, tokensToSellBn: BigNumber) {
28
24
  const totalTokensSold = new Decimal(sale.fetchTokensSold());
@@ -72,10 +68,15 @@ function calculateNativeTokensReceived(sale: LaunchpadSale, tokensToSellBn: BigN
72
68
  export async function callNativeTokenOut(ctx: GalaChainContext, sellTokenDTO: ExactTokenQuantityDto) {
73
69
  const sale = await fetchAndValidateSale(ctx, sellTokenDTO.vaultAddress);
74
70
  const nativeTokensReceived = calculateNativeTokensReceived(sale, sellTokenDTO.tokenQuantity);
71
+ const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
75
72
  return {
76
73
  calculatedQuantity: nativeTokensReceived,
77
74
  extraFees: {
78
- reverseBondingCurve: calculateReverseBondingCurveFee(sale, BigNumber(nativeTokensReceived)).toString()
75
+ reverseBondingCurve: calculateReverseBondingCurveFee(sale, BigNumber(nativeTokensReceived)).toString(),
76
+ transactionFees: calculateTransactionFee(
77
+ BigNumber(nativeTokensReceived),
78
+ launchpadFeeAddressConfiguration?.feeAmount
79
+ )
79
80
  }
80
81
  };
81
82
  }