@gala-chain/launchpad 1.0.15 → 1.0.16

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 (49) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/src/api/types/LaunchpadDtos.d.ts +2 -1
  3. package/lib/src/api/types/LaunchpadDtos.d.ts.map +1 -1
  4. package/lib/src/api/types/LaunchpadDtos.js +11 -1
  5. package/lib/src/api/types/LaunchpadDtos.js.map +1 -1
  6. package/lib/src/api/types/LaunchpadSale.d.ts +6 -1
  7. package/lib/src/api/types/LaunchpadSale.d.ts.map +1 -1
  8. package/lib/src/api/types/LaunchpadSale.js +21 -6
  9. package/lib/src/api/types/LaunchpadSale.js.map +1 -1
  10. package/lib/src/chaincode/launchpad/buyWithNative.d.ts.map +1 -1
  11. package/lib/src/chaincode/launchpad/buyWithNative.js +4 -1
  12. package/lib/src/chaincode/launchpad/buyWithNative.js.map +1 -1
  13. package/lib/src/chaincode/launchpad/callMemeTokenIn.d.ts.map +1 -1
  14. package/lib/src/chaincode/launchpad/callMemeTokenIn.js +6 -4
  15. package/lib/src/chaincode/launchpad/callMemeTokenIn.js.map +1 -1
  16. package/lib/src/chaincode/launchpad/callMemeTokenOut.d.ts.map +1 -1
  17. package/lib/src/chaincode/launchpad/callMemeTokenOut.js +19 -8
  18. package/lib/src/chaincode/launchpad/callMemeTokenOut.js.map +1 -1
  19. package/lib/src/chaincode/launchpad/callNativeTokenIn.d.ts.map +1 -1
  20. package/lib/src/chaincode/launchpad/callNativeTokenIn.js +13 -6
  21. package/lib/src/chaincode/launchpad/callNativeTokenIn.js.map +1 -1
  22. package/lib/src/chaincode/launchpad/callNativeTokenOut.d.ts.map +1 -1
  23. package/lib/src/chaincode/launchpad/callNativeTokenOut.js +6 -4
  24. package/lib/src/chaincode/launchpad/callNativeTokenOut.js.map +1 -1
  25. package/lib/src/chaincode/launchpad/createSale.d.ts.map +1 -1
  26. package/lib/src/chaincode/launchpad/createSale.js +8 -6
  27. package/lib/src/chaincode/launchpad/createSale.js.map +1 -1
  28. package/lib/src/chaincode/launchpad/finaliseSale.js +2 -2
  29. package/lib/src/chaincode/launchpad/finaliseSale.js.map +1 -1
  30. package/lib/src/chaincode/utils/launchpadSaleUtils.d.ts +1 -1
  31. package/lib/src/chaincode/utils/launchpadSaleUtils.d.ts.map +1 -1
  32. package/lib/src/chaincode/utils/launchpadSaleUtils.js +5 -2
  33. package/lib/src/chaincode/utils/launchpadSaleUtils.js.map +1 -1
  34. package/lib/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +1 -1
  36. package/src/api/types/LaunchpadDtos.ts +12 -1
  37. package/src/api/types/LaunchpadSale.ts +34 -6
  38. package/src/chaincode/launchpad/buyExactToken.spec.ts +233 -0
  39. package/src/chaincode/launchpad/buyWithNative.spec.ts +61 -1
  40. package/src/chaincode/launchpad/buyWithNative.ts +5 -1
  41. package/src/chaincode/launchpad/callMemeTokenIn.ts +11 -4
  42. package/src/chaincode/launchpad/callMemeTokenOut.ts +24 -8
  43. package/src/chaincode/launchpad/callNativeTokenIn.ts +18 -7
  44. package/src/chaincode/launchpad/callNativeTokenOut.ts +10 -4
  45. package/src/chaincode/launchpad/createSale.ts +10 -5
  46. package/src/chaincode/launchpad/finaliseSale.ts +2 -2
  47. package/src/chaincode/launchpad/sellExactToken.spec.ts +139 -2
  48. package/src/chaincode/launchpad/sellWithNative.spec.ts +157 -1
  49. package/src/chaincode/utils/launchpadSaleUtils.ts +6 -2
@@ -203,8 +203,8 @@ function calculateFinalLaunchpadPrice(
203
203
  areTokensSorted: boolean
204
204
  ): { sqrtPrice: BigNumber; finalPrice: BigNumber } {
205
205
  const totalTokensSold = new Decimal(sale.fetchTokensSold());
206
- const basePrice = new Decimal(LaunchpadSale.BASE_PRICE);
207
- const { exponentFactor, euler, decimals } = getBondingConstants();
206
+ const basePrice = new Decimal(sale.basePrice.toString());
207
+ const { exponentFactor, euler, decimals } = getBondingConstants(sale.adjustableSupplyMultiplier);
208
208
 
209
209
  const exponent = exponentFactor.mul(totalTokensSold).div(decimals);
210
210
  const multiplicand = euler.pow(exponent);
@@ -21,11 +21,11 @@ import {
21
21
  asValidUserAlias,
22
22
  randomUniqueKey
23
23
  } from "@gala-chain/api";
24
- import { currency, fixture, users } from "@gala-chain/test";
24
+ import { currency, fixture, transactionSuccess, users } from "@gala-chain/test";
25
25
  import BigNumber from "bignumber.js";
26
26
  import { plainToInstance } from "class-transformer";
27
27
 
28
- import { ExactTokenQuantityDto, LaunchpadSale } from "../../api/types";
28
+ import { ExactTokenQuantityDto, LaunchpadSale, TradeResDto } from "../../api/types";
29
29
  import { LaunchpadContract } from "../LaunchpadContract";
30
30
  import launchpadgala from "../test/launchpadgala";
31
31
 
@@ -204,4 +204,141 @@ describe("sellExactToken", () => {
204
204
  expect(response.Data?.inputQuantity).toBe("500");
205
205
  expect(new BigNumber(response.Data?.outputQuantity || "0").isPositive()).toBe(true);
206
206
  });
207
+
208
+ let galaPurchaseQtyDefaultSupply: BigNumber;
209
+
210
+ test("Adjustable supply: Single transaction yields expected value for default 10 Million supply", async () => {
211
+ // Given
212
+ const multiplier = undefined;
213
+
214
+ sale = new LaunchpadSale(
215
+ vaultAddress,
216
+ currencyInstance.instanceKeyObj(),
217
+ undefined,
218
+ users.testUser1.identityKey,
219
+ undefined,
220
+ multiplier
221
+ );
222
+
223
+ const { ctx, contract } = fixture(LaunchpadContract)
224
+ .registeredUsers(users.testUser1)
225
+ .savedState(
226
+ currencyClass,
227
+ currencyInstance,
228
+ launchpadGalaClass,
229
+ launchpadGalaInstance,
230
+ sale,
231
+ salelaunchpadGalaBalance,
232
+ saleCurrencyBalance,
233
+ userlaunchpadGalaBalance,
234
+ userCurrencyBalance
235
+ );
236
+
237
+ const buyDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("500"));
238
+
239
+ buyDto.uniqueKey = randomUniqueKey();
240
+ buyDto.sign(users.testUser1.privateKey);
241
+
242
+ const expectedBuyResponse = plainToInstance(TradeResDto, {
243
+ inputQuantity: "0.00825575",
244
+ totalFees: "0",
245
+ totalTokenSold: new BigNumber("500").toString(),
246
+ outputQuantity: new BigNumber("500").toString(),
247
+ tokenName: "AUTOMATEDTESTCOIN",
248
+ tradeType: "Buy",
249
+ uniqueKey: buyDto.uniqueKey,
250
+ vaultAddress: "service|GALA$Unit$none$none$launchpad",
251
+ userAddress: "client|testUser1",
252
+ isFinalized: false,
253
+ functionName: "BuyExactToken"
254
+ });
255
+
256
+ const sellDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("50"));
257
+ sellDto.uniqueKey = randomUniqueKey();
258
+ const signedDto = sellDto.signed(users.testUser1.privateKey);
259
+
260
+ // When
261
+ const buyRes = await contract.BuyExactToken(ctx, buyDto);
262
+
263
+ const sellRes = await contract.SellExactToken(ctx, signedDto);
264
+
265
+ // Then
266
+ expect(buyRes).toEqual(transactionSuccess(expectedBuyResponse));
267
+
268
+ expect(sellRes.Status).toBe(1);
269
+ expect(sellRes.Data?.inputQuantity).toBe("50");
270
+ expect(sellRes.Data?.outputQuantity).toBe("0.00082579");
271
+
272
+ galaPurchaseQtyDefaultSupply = new BigNumber(sellRes.Data?.outputQuantity ?? 0);
273
+ });
274
+
275
+ test("Adjustable supply: Single transaction yields expected quantity for 100x scaled 1 Billion supply", async () => {
276
+ // Given
277
+ const multiplier = 100;
278
+ const inputQty = new BigNumber("50").times(multiplier);
279
+
280
+ sale = new LaunchpadSale(
281
+ vaultAddress,
282
+ currencyInstance.instanceKeyObj(),
283
+ undefined,
284
+ users.testUser1.identityKey,
285
+ undefined,
286
+ multiplier
287
+ );
288
+
289
+ const { ctx, contract } = fixture(LaunchpadContract)
290
+ .registeredUsers(users.testUser1)
291
+ .savedState(
292
+ currencyClass,
293
+ currencyInstance,
294
+ launchpadGalaClass,
295
+ launchpadGalaInstance,
296
+ sale,
297
+ salelaunchpadGalaBalance,
298
+ saleCurrencyBalance,
299
+ userlaunchpadGalaBalance,
300
+ userCurrencyBalance
301
+ );
302
+
303
+ const buyDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("500").times(multiplier));
304
+
305
+ buyDto.uniqueKey = randomUniqueKey();
306
+ buyDto.sign(users.testUser1.privateKey);
307
+
308
+ const expectedBuyResponse = plainToInstance(TradeResDto, {
309
+ inputQuantity: "0.00825575",
310
+ totalFees: "0",
311
+ totalTokenSold: new BigNumber("500").times(multiplier).toString(),
312
+ outputQuantity: new BigNumber("500").times(multiplier).toString(),
313
+ tokenName: "AUTOMATEDTESTCOIN",
314
+ tradeType: "Buy",
315
+ uniqueKey: buyDto.uniqueKey,
316
+ vaultAddress: "service|GALA$Unit$none$none$launchpad",
317
+ userAddress: "client|testUser1",
318
+ isFinalized: false,
319
+ functionName: "BuyExactToken"
320
+ });
321
+
322
+ const sellDto = new ExactTokenQuantityDto(vaultAddress, inputQty);
323
+ sellDto.uniqueKey = randomUniqueKey();
324
+ const signedDto = sellDto.signed(users.testUser1.privateKey);
325
+
326
+ // When
327
+ const buyRes = await contract.BuyExactToken(ctx, buyDto);
328
+
329
+ const sellRes = await contract.SellExactToken(ctx, signedDto);
330
+
331
+ // Then
332
+ expect(buyRes).toEqual(transactionSuccess(expectedBuyResponse));
333
+
334
+ expect(sellRes.Status).toBe(1);
335
+ expect(sellRes.Data?.inputQuantity).toBe(inputQty.toString());
336
+ expect(sellRes.Data?.outputQuantity).toBe("0.00082579");
337
+
338
+ const galaPurchaseQty100xSupply = new BigNumber(sellRes.Data?.outputQuantity ?? -1);
339
+
340
+ // Compared to the previous test where the Launchpad has the default 10 Million supply,
341
+ // We expect the Meme token Qty to scale 100x and the Gala Qty to remain the same
342
+ expect(galaPurchaseQtyDefaultSupply).toEqual(galaPurchaseQty100xSupply);
343
+ });
207
344
  });
@@ -26,7 +26,7 @@ import { currency, fixture, transactionError, transactionSuccess, users } from "
26
26
  import BigNumber from "bignumber.js";
27
27
  import { plainToInstance } from "class-transformer";
28
28
 
29
- import { LaunchpadSale, NativeTokenQuantityDto, TradeResDto } from "../../api/types";
29
+ import { ExactTokenQuantityDto, LaunchpadSale, NativeTokenQuantityDto, TradeResDto } from "../../api/types";
30
30
  import { LaunchpadContract } from "../LaunchpadContract";
31
31
  import launchpadgala from "../test/launchpadgala";
32
32
 
@@ -286,4 +286,160 @@ describe("sellWithNative", () => {
286
286
 
287
287
  // todo: check writes map, verify vault balance
288
288
  });
289
+
290
+ let galaPurchaseQtyDefaultSupply: BigNumber;
291
+ let memeSaleQtyDefaultSupply: BigNumber;
292
+
293
+ test("Adjustable supply: Single transaction yields expected value for default 10 Million supply", async () => {
294
+ // Given
295
+ const multiplier = undefined;
296
+ galaPurchaseQtyDefaultSupply = new BigNumber("0.00082579");
297
+ memeSaleQtyDefaultSupply = new BigNumber("49.999949130655");
298
+
299
+ sale = new LaunchpadSale(
300
+ vaultAddress,
301
+ currencyInstance.instanceKeyObj(),
302
+ undefined,
303
+ users.testUser1.identityKey,
304
+ undefined,
305
+ multiplier
306
+ );
307
+
308
+ const { ctx, contract } = fixture(LaunchpadContract)
309
+ .registeredUsers(users.testUser1)
310
+ .savedState(
311
+ currencyClass,
312
+ currencyInstance,
313
+ launchpadGalaClass,
314
+ launchpadGalaInstance,
315
+ sale,
316
+ salelaunchpadGalaBalance,
317
+ saleCurrencyBalance,
318
+ userlaunchpadGalaBalance,
319
+ userCurrencyBalance
320
+ );
321
+
322
+ const buyDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("500"));
323
+
324
+ buyDto.uniqueKey = randomUniqueKey();
325
+ buyDto.sign(users.testUser1.privateKey);
326
+
327
+ const expectedBuyResponse = plainToInstance(TradeResDto, {
328
+ inputQuantity: "0.00825575",
329
+ totalFees: "0",
330
+ totalTokenSold: new BigNumber("500").toString(),
331
+ outputQuantity: new BigNumber("500").toString(),
332
+ tokenName: "AUTOMATEDTESTCOIN",
333
+ tradeType: "Buy",
334
+ uniqueKey: buyDto.uniqueKey,
335
+ vaultAddress: "service|GALA$Unit$none$none$launchpad",
336
+ userAddress: "client|testUser1",
337
+ isFinalized: false,
338
+ functionName: "BuyExactToken"
339
+ });
340
+
341
+ const sellDto = new NativeTokenQuantityDto(vaultAddress, galaPurchaseQtyDefaultSupply);
342
+ sellDto.uniqueKey = randomUniqueKey();
343
+ const signedDto = sellDto.signed(users.testUser1.privateKey);
344
+
345
+ // When
346
+ const buyRes = await contract.BuyExactToken(ctx, buyDto);
347
+
348
+ const sellRes = await contract.SellWithNative(ctx, signedDto);
349
+
350
+ // Then
351
+ expect(buyRes).toEqual(transactionSuccess(expectedBuyResponse));
352
+
353
+ expect(sellRes).toEqual(
354
+ transactionSuccess(
355
+ expect.objectContaining({
356
+ outputQuantity: galaPurchaseQtyDefaultSupply.toString(),
357
+ // extra precision in set constant above accounts for loss of precision
358
+ // when increased by the multiplier below.
359
+ // here, we round to the token decimal places to match the internal logic
360
+ inputQuantity: memeSaleQtyDefaultSupply.decimalPlaces(10).toString()
361
+ })
362
+ )
363
+ );
364
+ galaPurchaseQtyDefaultSupply = new BigNumber(sellRes.Data?.outputQuantity ?? 0);
365
+ });
366
+
367
+ test("Adjustable supply: Single transaction yields expected quantity for 100x scaled 1 Billion supply", async () => {
368
+ // Given
369
+ const multiplier = 100;
370
+
371
+ // Same Gala purchase amount should buy 100x meme token output
372
+ const inputQty = new BigNumber(galaPurchaseQtyDefaultSupply);
373
+
374
+ sale = new LaunchpadSale(
375
+ vaultAddress,
376
+ currencyInstance.instanceKeyObj(),
377
+ undefined,
378
+ users.testUser1.identityKey,
379
+ undefined,
380
+ multiplier
381
+ );
382
+
383
+ const { ctx, contract } = fixture(LaunchpadContract)
384
+ .registeredUsers(users.testUser1)
385
+ .savedState(
386
+ currencyClass,
387
+ currencyInstance,
388
+ launchpadGalaClass,
389
+ launchpadGalaInstance,
390
+ sale,
391
+ salelaunchpadGalaBalance,
392
+ saleCurrencyBalance,
393
+ userlaunchpadGalaBalance,
394
+ userCurrencyBalance
395
+ );
396
+
397
+ const buyDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("500").times(multiplier));
398
+
399
+ buyDto.uniqueKey = randomUniqueKey();
400
+ buyDto.sign(users.testUser1.privateKey);
401
+
402
+ const expectedBuyResponse = plainToInstance(TradeResDto, {
403
+ inputQuantity: "0.00825575",
404
+ totalFees: "0",
405
+ totalTokenSold: new BigNumber("500").times(multiplier).toString(),
406
+ outputQuantity: new BigNumber("500").times(multiplier).toString(),
407
+ tokenName: "AUTOMATEDTESTCOIN",
408
+ tradeType: "Buy",
409
+ uniqueKey: buyDto.uniqueKey,
410
+ vaultAddress: "service|GALA$Unit$none$none$launchpad",
411
+ userAddress: "client|testUser1",
412
+ isFinalized: false,
413
+ functionName: "BuyExactToken"
414
+ });
415
+
416
+ const sellDto = new NativeTokenQuantityDto(vaultAddress, inputQty);
417
+ sellDto.uniqueKey = randomUniqueKey();
418
+ const signedDto = sellDto.signed(users.testUser1.privateKey);
419
+
420
+ // When
421
+ const buyRes = await contract.BuyExactToken(ctx, buyDto);
422
+
423
+ const sellRes = await contract.SellWithNative(ctx, signedDto);
424
+
425
+ // Then
426
+ expect(buyRes).toEqual(transactionSuccess(expectedBuyResponse));
427
+
428
+ expect(sellRes).toEqual(
429
+ transactionSuccess(
430
+ expect.objectContaining({
431
+ inputQuantity: memeSaleQtyDefaultSupply.times(multiplier).toString(),
432
+ outputQuantity: galaPurchaseQtyDefaultSupply.toString()
433
+ })
434
+ )
435
+ );
436
+
437
+ const galaPurchaseQty100xSupply = new BigNumber(sellRes.Data?.outputQuantity ?? -1);
438
+ const memeSaleQty100xSupply = new BigNumber(sellRes.Data?.inputQuantity ?? -1);
439
+
440
+ // Compared to the previous test where the Launchpad has the default 10 Million supply,
441
+ // We expect the Meme token Qty to scale 100x and the Gala Qty to remain the same
442
+ expect(galaPurchaseQtyDefaultSupply).toEqual(galaPurchaseQty100xSupply);
443
+ expect(memeSaleQtyDefaultSupply).toEqual(memeSaleQty100xSupply.dividedBy(multiplier));
444
+ });
289
445
  });
@@ -54,9 +54,13 @@ export async function fetchAndValidateSale(
54
54
  return sale;
55
55
  }
56
56
 
57
- export function getBondingConstants() {
57
+ export function getBondingConstants(multiplier?: number) {
58
+ const exponentFactor =
59
+ multiplier && multiplier > 0
60
+ ? new Decimal("1166069000000").times(1 / multiplier)
61
+ : new Decimal("1166069000000");
58
62
  return {
59
- exponentFactor: new Decimal("1166069000000"), // exponent factor / b
63
+ exponentFactor: exponentFactor, // exponent factor / b
60
64
  euler: new Decimal("2.7182818284590452353602874713527"), // e
61
65
  decimals: new Decimal("1e+18") // scaling factor for decimals
62
66
  };