@gala-chain/launchpad 1.0.13 → 1.0.15

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 (87) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/src/api/types/LaunchpadDtos.d.ts +3 -1
  3. package/lib/src/api/types/LaunchpadDtos.d.ts.map +1 -1
  4. package/lib/src/api/types/LaunchpadDtos.js +14 -1
  5. package/lib/src/api/types/LaunchpadDtos.js.map +1 -1
  6. package/lib/src/api/types/LaunchpadSale.d.ts +5 -2
  7. package/lib/src/api/types/LaunchpadSale.d.ts.map +1 -1
  8. package/lib/src/api/types/LaunchpadSale.js +35 -9
  9. package/lib/src/api/types/LaunchpadSale.js.map +1 -1
  10. package/lib/src/chaincode/LaunchpadContract.js +6 -6
  11. package/lib/src/chaincode/LaunchpadContract.js.map +1 -1
  12. package/lib/src/chaincode/launchpad/buyExactToken.d.ts.map +1 -1
  13. package/lib/src/chaincode/launchpad/buyExactToken.js +18 -42
  14. package/lib/src/chaincode/launchpad/buyExactToken.js.map +1 -1
  15. package/lib/src/chaincode/launchpad/buyWithNative.d.ts.map +1 -1
  16. package/lib/src/chaincode/launchpad/buyWithNative.js +12 -43
  17. package/lib/src/chaincode/launchpad/buyWithNative.js.map +1 -1
  18. package/lib/src/chaincode/launchpad/callMemeTokenIn.d.ts +4 -10
  19. package/lib/src/chaincode/launchpad/callMemeTokenIn.d.ts.map +1 -1
  20. package/lib/src/chaincode/launchpad/callMemeTokenIn.js +13 -9
  21. package/lib/src/chaincode/launchpad/callMemeTokenIn.js.map +1 -1
  22. package/lib/src/chaincode/launchpad/callMemeTokenOut.d.ts +4 -10
  23. package/lib/src/chaincode/launchpad/callMemeTokenOut.d.ts.map +1 -1
  24. package/lib/src/chaincode/launchpad/callMemeTokenOut.js +46 -22
  25. package/lib/src/chaincode/launchpad/callMemeTokenOut.js.map +1 -1
  26. package/lib/src/chaincode/launchpad/callNativeTokenIn.d.ts +4 -10
  27. package/lib/src/chaincode/launchpad/callNativeTokenIn.d.ts.map +1 -1
  28. package/lib/src/chaincode/launchpad/callNativeTokenIn.js +35 -14
  29. package/lib/src/chaincode/launchpad/callNativeTokenIn.js.map +1 -1
  30. package/lib/src/chaincode/launchpad/callNativeTokenOut.d.ts +4 -10
  31. package/lib/src/chaincode/launchpad/callNativeTokenOut.d.ts.map +1 -1
  32. package/lib/src/chaincode/launchpad/callNativeTokenOut.js +17 -12
  33. package/lib/src/chaincode/launchpad/callNativeTokenOut.js.map +1 -1
  34. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.js +1 -1
  35. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.js.map +1 -1
  36. package/lib/src/chaincode/launchpad/createSale.d.ts.map +1 -1
  37. package/lib/src/chaincode/launchpad/createSale.js +15 -1
  38. package/lib/src/chaincode/launchpad/createSale.js.map +1 -1
  39. package/lib/src/chaincode/launchpad/fees.d.ts +11 -0
  40. package/lib/src/chaincode/launchpad/fees.d.ts.map +1 -1
  41. package/lib/src/chaincode/launchpad/fees.js +42 -3
  42. package/lib/src/chaincode/launchpad/fees.js.map +1 -1
  43. package/lib/src/chaincode/launchpad/finaliseSale.d.ts.map +1 -1
  44. package/lib/src/chaincode/launchpad/finaliseSale.js +7 -4
  45. package/lib/src/chaincode/launchpad/finaliseSale.js.map +1 -1
  46. package/lib/src/chaincode/launchpad/sellExactToken.d.ts.map +1 -1
  47. package/lib/src/chaincode/launchpad/sellExactToken.js +14 -23
  48. package/lib/src/chaincode/launchpad/sellExactToken.js.map +1 -1
  49. package/lib/src/chaincode/launchpad/sellWithNative.d.ts.map +1 -1
  50. package/lib/src/chaincode/launchpad/sellWithNative.js +10 -19
  51. package/lib/src/chaincode/launchpad/sellWithNative.js.map +1 -1
  52. package/lib/src/chaincode/test/launchpadgala.d.ts.map +1 -1
  53. package/lib/src/chaincode/test/launchpadgala.js +2 -1
  54. package/lib/src/chaincode/test/launchpadgala.js.map +1 -1
  55. package/lib/src/chaincode/utils/launchpadSaleUtils.d.ts +4 -0
  56. package/lib/src/chaincode/utils/launchpadSaleUtils.d.ts.map +1 -1
  57. package/lib/src/chaincode/utils/launchpadSaleUtils.js +19 -1
  58. package/lib/src/chaincode/utils/launchpadSaleUtils.js.map +1 -1
  59. package/lib/src/cli.js +3 -1
  60. package/lib/src/cli.js.map +1 -1
  61. package/lib/tsconfig.tsbuildinfo +1 -1
  62. package/package.json +1 -1
  63. package/src/api/types/LaunchpadDtos.ts +15 -1
  64. package/src/api/types/LaunchpadSale.ts +32 -10
  65. package/src/chaincode/LaunchpadContract.ts +3 -3
  66. package/src/chaincode/launchpad/buyExactToken.spec.ts +3 -38
  67. package/src/chaincode/launchpad/buyExactToken.ts +22 -56
  68. package/src/chaincode/launchpad/buyWithNative.spec.ts +105 -45
  69. package/src/chaincode/launchpad/buyWithNative.ts +15 -65
  70. package/src/chaincode/launchpad/callMemeTokenIn.ts +36 -12
  71. package/src/chaincode/launchpad/callMemeTokenOut.spec.ts +2 -2
  72. package/src/chaincode/launchpad/callMemeTokenOut.ts +72 -26
  73. package/src/chaincode/launchpad/callNativeTokenIn.ts +62 -19
  74. package/src/chaincode/launchpad/callNativeTokenOut.ts +38 -15
  75. package/src/chaincode/launchpad/configureLaunchpadFeeConfig.spec.ts +0 -1
  76. package/src/chaincode/launchpad/configureLaunchpadFeeConfig.ts +1 -1
  77. package/src/chaincode/launchpad/createSale.ts +26 -3
  78. package/src/chaincode/launchpad/fees.ts +55 -3
  79. package/src/chaincode/launchpad/finaliseSale.ts +7 -4
  80. package/src/chaincode/launchpad/launchpadBatchSubmitAuthorizations.spec.ts +150 -68
  81. package/src/chaincode/launchpad/sellExactToken.spec.ts +4 -81
  82. package/src/chaincode/launchpad/sellExactToken.ts +16 -25
  83. package/src/chaincode/launchpad/sellWithNative.spec.ts +2 -42
  84. package/src/chaincode/launchpad/sellWithNative.ts +14 -23
  85. package/src/chaincode/test/launchpadgala.ts +3 -1
  86. package/src/chaincode/utils/launchpadSaleUtils.ts +25 -1
  87. package/src/cli.ts +3 -1
@@ -18,9 +18,9 @@ import { BigNumber } from "bignumber.js";
18
18
 
19
19
  import { ExactTokenQuantityDto, TradeResDto } from "../../api/types";
20
20
  import { SlippageToleranceExceededError } from "../../api/utils/error";
21
- import { fetchAndValidateSale, fetchLaunchpadFeeAddress } from "../utils";
21
+ import { fetchAndValidateSale } from "../utils";
22
22
  import { callNativeTokenOut } from "./callNativeTokenOut";
23
- import { payReverseBondingCurveFee } from "./fees";
23
+ import { payReverseBondingCurveFee, transferTransactionFees } from "./fees";
24
24
 
25
25
  /**
26
26
  * Executes the sale of an exact amount of tokens for native tokens (e.g., GALA).
@@ -49,25 +49,26 @@ export async function sellExactToken(
49
49
 
50
50
  // Determine how much native token (e.g., GALA) the user will receive for the exact token quantity
51
51
  const callNativeTokenOutResult = await callNativeTokenOut(ctx, sellTokenDTO);
52
- const nativeTokensToProvide = new BigNumber(callNativeTokenOutResult.calculatedQuantity);
53
- const transactionFees = callNativeTokenOutResult.extraFees.transactionFees;
52
+ const tokensBeingSold = new BigNumber(callNativeTokenOutResult.originalQuantity); // number of tokens user wants to sell
53
+ const nativeTokensPayout = new BigNumber(callNativeTokenOutResult.calculatedQuantity); // number of native tokens user will receive
54
+ const transactionFees = new BigNumber(callNativeTokenOutResult.extraFees.transactionFees); // transaction fees
54
55
 
55
56
  const nativeTokensLeftInVault = new BigNumber(sale.nativeTokenQuantity);
56
57
  const nativeToken = sale.fetchNativeTokenInstanceKey();
57
58
  const memeToken = sale.fetchSellingTokenInstanceKey();
58
59
 
59
60
  // Abort if the vault doesn't have enough native tokens to pay the user
60
- if (nativeTokensLeftInVault.comparedTo(nativeTokensToProvide) < 0) {
61
+ if (nativeTokensPayout.isGreaterThan(nativeTokensLeftInVault)) {
61
62
  throw new ValidationFailedError("Not enough GALA in sale contract to carry out this operation.");
62
63
  }
63
64
 
64
65
  // Enforce slippage tolerance: expected amount must not be greater than what will actually be received
65
66
  if (
66
67
  sellTokenDTO.expectedNativeToken &&
67
- sellTokenDTO.expectedNativeToken.comparedTo(nativeTokensToProvide) > 0
68
+ sellTokenDTO.expectedNativeToken.isGreaterThan(nativeTokensPayout)
68
69
  ) {
69
70
  throw new SlippageToleranceExceededError(
70
- `expected ${sellTokenDTO.expectedNativeToken.toString()}, but only ${nativeTokensToProvide.toString()} tokens can be provided. Reduce the expected amount or adjust your slippage tolerance.`
71
+ `expected ${sellTokenDTO.expectedNativeToken.toString()}, but only ${nativeTokensPayout.toString()} tokens can be provided. Reduce the expected amount or adjust your slippage tolerance.`
71
72
  );
72
73
  }
73
74
 
@@ -76,29 +77,19 @@ export async function sellExactToken(
76
77
  await payReverseBondingCurveFee(
77
78
  ctx,
78
79
  sale,
79
- nativeTokensToProvide,
80
+ nativeTokensPayout,
80
81
  sellTokenDTO.extraFees?.maxAcceptableReverseBondingCurveFee
81
82
  );
82
83
 
83
84
  // Transfer launchpad transaction fee if applicable
84
- const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
85
- if (launchpadFeeAddressConfiguration && transactionFees) {
86
- await transferToken(ctx, {
87
- from: ctx.callingUser,
88
- to: launchpadFeeAddressConfiguration.feeAddress,
89
- tokenInstanceKey: nativeToken,
90
- quantity: new BigNumber(transactionFees),
91
- allowancesToUse: [],
92
- authorizedOnBehalf: undefined
93
- });
94
- }
85
+ await transferTransactionFees(ctx, sale, transactionFees, nativeToken);
95
86
 
96
87
  // Transfer meme tokens from user to vault
97
88
  await transferToken(ctx, {
98
89
  from: ctx.callingUser,
99
90
  to: sellTokenDTO.vaultAddress,
100
91
  tokenInstanceKey: memeToken,
101
- quantity: sellTokenDTO.tokenQuantity,
92
+ quantity: tokensBeingSold,
102
93
  allowancesToUse: [],
103
94
  authorizedOnBehalf: undefined
104
95
  });
@@ -108,7 +99,7 @@ export async function sellExactToken(
108
99
  from: sellTokenDTO.vaultAddress,
109
100
  to: ctx.callingUser,
110
101
  tokenInstanceKey: nativeToken,
111
- quantity: nativeTokensToProvide,
102
+ quantity: nativeTokensPayout,
112
103
  allowancesToUse: [],
113
104
  authorizedOnBehalf: {
114
105
  callingOnBehalf: sellTokenDTO.vaultAddress,
@@ -117,16 +108,16 @@ export async function sellExactToken(
117
108
  });
118
109
 
119
110
  // Update sale state with this transaction
120
- sale.sellToken(sellTokenDTO.tokenQuantity, nativeTokensToProvide);
111
+ sale.sellToken(tokensBeingSold, nativeTokensPayout);
121
112
  await putChainObject(ctx, sale);
122
113
 
123
114
  const token = await fetchTokenClass(ctx, sale.sellingToken);
124
115
  return {
125
- inputQuantity: sellTokenDTO.tokenQuantity.toFixed(),
126
- totalFees: new BigNumber(transactionFees)
116
+ inputQuantity: tokensBeingSold.toFixed(),
117
+ totalFees: transactionFees
127
118
  .plus(sellTokenDTO.extraFees?.maxAcceptableReverseBondingCurveFee ?? 0)
128
119
  .toFixed(),
129
- outputQuantity: nativeTokensToProvide.toFixed(),
120
+ outputQuantity: nativeTokensPayout.toFixed(),
130
121
  tokenName: token.name,
131
122
  tradeType: "Sell",
132
123
  vaultAddress: sellTokenDTO.vaultAddress,
@@ -125,46 +125,6 @@ describe("sellWithNative", () => {
125
125
  );
126
126
  });
127
127
 
128
- it("should reject sell when dto contains fractional precision greater than native TokenClass.decimals", async () => {
129
- // Given - Setup meme token with 0 decimals to force decimal precision error
130
- const zeroDecimalLaunchpadGalaClass = plainToInstance(TokenClass, {
131
- ...launchpadgala.tokenClassPlain(),
132
- decimals: 8 // This codebase currently hard-codes 8 as NATIVE_TOKEN_DECIMALS...
133
- });
134
-
135
- // Simulate prior buys to establish sale state with native tokens
136
- sale.buyToken(new BigNumber("100"), new BigNumber("100"));
137
-
138
- const { ctx, contract } = fixture(LaunchpadContract)
139
- .registeredUsers(users.testUser1)
140
- .savedState(
141
- currencyClass,
142
- currencyInstance,
143
- zeroDecimalLaunchpadGalaClass,
144
- launchpadGalaInstance,
145
- sale,
146
- salelaunchpadGalaBalance,
147
- saleCurrencyBalance,
148
- userlaunchpadGalaBalance,
149
- userCurrencyBalance
150
- );
151
-
152
- // Request native tokens that will require fractional meme tokens from bonding curve
153
- const sellDto = new NativeTokenQuantityDto(vaultAddress, new BigNumber("0.123456789"));
154
- sellDto.uniqueKey = randomUniqueKey();
155
- sellDto.sign(users.testUser1.privateKey);
156
-
157
- // When
158
- const response = await contract.SellWithNative(ctx, sellDto);
159
-
160
- // Then - Expect error due to decimal precision mismatch
161
- expect(response).toEqual(
162
- transactionError(
163
- new InvalidDecimalError(sellDto.nativeTokenQuantity, zeroDecimalLaunchpadGalaClass.decimals)
164
- )
165
- );
166
- });
167
-
168
128
  it("should sell tokens for native currency successfully", async () => {
169
129
  // Given
170
130
  sale.buyToken(new BigNumber("10000"), new BigNumber("10")); // Users bought tokens, sale now has GALA
@@ -188,12 +148,12 @@ describe("sellWithNative", () => {
188
148
 
189
149
  const expectedResponse = plainToInstance(TradeResDto, {
190
150
  functionName: "SellWithNative",
191
- inputQuantity: "6008.9271949682",
151
+ inputQuantity: "6008.9271949683",
192
152
  isFinalized: false,
193
153
  outputQuantity: "0.1",
194
154
  tokenName: "AUTOMATEDTESTCOIN",
195
155
  totalFees: "0",
196
- totalTokenSold: "3991.0728050318",
156
+ totalTokenSold: "3991.0728050317",
197
157
  tradeType: "Sell",
198
158
  uniqueKey: sellDto.uniqueKey,
199
159
  userAddress: "client|testUser1",
@@ -22,11 +22,11 @@ import {
22
22
  } from "@gala-chain/chaincode";
23
23
  import BigNumber from "bignumber.js";
24
24
 
25
- import { LaunchpadSale, NativeTokenQuantityDto, TradeResDto } from "../../api/types";
25
+ import { NativeTokenQuantityDto, TradeResDto } from "../../api/types";
26
26
  import { SlippageToleranceExceededError } from "../../api/utils/error";
27
- import { fetchAndValidateSale, fetchLaunchpadFeeAddress } from "../utils";
27
+ import { fetchAndValidateSale } from "../utils";
28
28
  import { callMemeTokenIn } from "./callMemeTokenIn";
29
- import { payReverseBondingCurveFee } from "./fees";
29
+ import { payReverseBondingCurveFee, transferTransactionFees } from "./fees";
30
30
 
31
31
  /**
32
32
  * Executes a sale of tokens using native tokens (e.g., GALA) in exchange for the specified token amount.
@@ -52,7 +52,7 @@ export async function sellWithNative(
52
52
  sellTokenDTO: NativeTokenQuantityDto
53
53
  ): Promise<TradeResDto> {
54
54
  // Fetch and validate the sale object
55
- const sale: LaunchpadSale = await fetchAndValidateSale(ctx, sellTokenDTO.vaultAddress);
55
+ const sale = await fetchAndValidateSale(ctx, sellTokenDTO.vaultAddress);
56
56
 
57
57
  const { collection, category, type, additionalKey } = sale.sellingToken;
58
58
  const sellingTokenCompositeKey = TokenClass.getCompositeKeyFromParts(TokenClass.INDEX_KEY, [
@@ -66,22 +66,23 @@ export async function sellWithNative(
66
66
  const nativeTokensLeftInVault = new BigNumber(sale.nativeTokenQuantity);
67
67
 
68
68
  // Cap nativeTokenQuantity to the vault balance if the requested amount exceeds it
69
- if (nativeTokensLeftInVault.comparedTo(sellTokenDTO.nativeTokenQuantity) < 0) {
69
+ if (nativeTokensLeftInVault.isLessThan(sellTokenDTO.nativeTokenQuantity)) {
70
70
  throw new ValidationFailedError("Not enough GALA in sale contract to carry out this operation.");
71
71
  }
72
72
 
73
73
  // Calculate how many tokens need to be sold to get the requested native amount
74
74
  const callMemeTokenInResult = await callMemeTokenIn(ctx, sellTokenDTO);
75
- const transactionFees = callMemeTokenInResult.extraFees.transactionFees;
75
+ const transactionFees = callMemeTokenInResult.extraFees.transactionFees; // transaction fees
76
+ const nativeTokensPayout = new BigNumber(callMemeTokenInResult.originalQuantity); // number of native tokens user wants to receive
76
77
  const tokensToSell = new BigNumber(callMemeTokenInResult.calculatedQuantity).decimalPlaces(
77
78
  sellingToken.decimals
78
- );
79
+ ); // number of tokens user needs to sell
79
80
 
80
81
  const nativeToken = sale.fetchNativeTokenInstanceKey();
81
82
  const memeToken = sale.fetchSellingTokenInstanceKey();
82
83
 
83
84
  // Enforce slippage tolerance
84
- if (sellTokenDTO.expectedToken && sellTokenDTO.expectedToken.comparedTo(tokensToSell) < 0) {
85
+ if (sellTokenDTO.expectedToken && sellTokenDTO.expectedToken.isLessThan(tokensToSell)) {
85
86
  throw new SlippageToleranceExceededError(
86
87
  `expected ${sellTokenDTO.expectedToken.toString()}, but at least ${tokensToSell.toString()} tokens are required. Increase the expected amount or adjust your slippage tolerance.`
87
88
  );
@@ -92,22 +93,12 @@ export async function sellWithNative(
92
93
  await payReverseBondingCurveFee(
93
94
  ctx,
94
95
  sale,
95
- sellTokenDTO.nativeTokenQuantity,
96
+ nativeTokensPayout,
96
97
  sellTokenDTO.extraFees?.maxAcceptableReverseBondingCurveFee
97
98
  );
98
99
 
99
100
  // Transfer launchpad transaction fees if applicable
100
- const launchpadFeeAddressConfiguration = await fetchLaunchpadFeeAddress(ctx);
101
- if (launchpadFeeAddressConfiguration && transactionFees) {
102
- await transferToken(ctx, {
103
- from: ctx.callingUser,
104
- to: launchpadFeeAddressConfiguration.feeAddress,
105
- tokenInstanceKey: nativeToken,
106
- quantity: new BigNumber(transactionFees),
107
- allowancesToUse: [],
108
- authorizedOnBehalf: undefined
109
- });
110
- }
101
+ await transferTransactionFees(ctx, sale, transactionFees, nativeToken);
111
102
 
112
103
  // Send meme tokens from user to vault
113
104
  await transferToken(ctx, {
@@ -124,7 +115,7 @@ export async function sellWithNative(
124
115
  from: sellTokenDTO.vaultAddress,
125
116
  to: ctx.callingUser,
126
117
  tokenInstanceKey: nativeToken,
127
- quantity: sellTokenDTO.nativeTokenQuantity,
118
+ quantity: nativeTokensPayout,
128
119
  allowancesToUse: [],
129
120
  authorizedOnBehalf: {
130
121
  callingOnBehalf: sellTokenDTO.vaultAddress,
@@ -133,7 +124,7 @@ export async function sellWithNative(
133
124
  });
134
125
 
135
126
  // Update internal sale tracking
136
- sale.sellToken(tokensToSell, sellTokenDTO.nativeTokenQuantity);
127
+ sale.sellToken(tokensToSell, nativeTokensPayout);
137
128
  await putChainObject(ctx, sale);
138
129
 
139
130
  const token = await fetchTokenClass(ctx, sale.sellingToken);
@@ -142,7 +133,7 @@ export async function sellWithNative(
142
133
  totalFees: new BigNumber(transactionFees)
143
134
  .plus(sellTokenDTO.extraFees?.maxAcceptableReverseBondingCurveFee ?? 0)
144
135
  .toFixed(),
145
- outputQuantity: sellTokenDTO.nativeTokenQuantity.toFixed(),
136
+ outputQuantity: nativeTokensPayout.toFixed(),
146
137
  tokenName: token.name,
147
138
  tradeType: "Sell",
148
139
  vaultAddress: sellTokenDTO.vaultAddress,
@@ -26,6 +26,8 @@ import { users } from "@gala-chain/test";
26
26
  import { createInstanceFn, createPlainFn } from "@gala-chain/test/lib/src/data/utils";
27
27
  import BigNumber from "bignumber.js";
28
28
 
29
+ import { LaunchpadSale } from "../../api/types";
30
+
29
31
  process.env.LAUNCHPAD_GALA_CLASS_COLLECTION = process.env.LAUNCHPAD_GALA_CLASS_COLLECTION ?? "GALA";
30
32
  process.env.LAUNCHPAD_GALA_CLASS_CATEGORY = process.env.LAUNCHPAD_GALA_CLASS_CATEGORY ?? "Unit";
31
33
  process.env.LAUNCHPAD_GALA_CLASS_TYPE = process.env.LAUNCHPAD_GALA_CLASS_TYPE ?? "none";
@@ -41,7 +43,7 @@ const tokenClassKeyPlain = createPlainFn({
41
43
  const tokenClassPlain = createPlainFn({
42
44
  ...tokenClassKeyPlain(),
43
45
  description: "Generated via automated test suite.",
44
- decimals: 8, // This codebase currently hard-codes 8 as NATIVE_TOKEN_DECIMALS
46
+ decimals: LaunchpadSale.NATIVE_TOKEN_DECIMALS,
45
47
  image: "https://app.gala.games/test-image-placeholder-url.png",
46
48
  isNonFungible: false,
47
49
  maxCapacity: new BigNumber(100000000000000),
@@ -13,7 +13,7 @@
13
13
  * limitations under the License.
14
14
  */
15
15
  import { ChainError, DefaultError, ErrorCode, NotFoundError } from "@gala-chain/api";
16
- import { GalaChainContext, getObjectByKey } from "@gala-chain/chaincode";
16
+ import { GalaChainContext, fetchTokenClass, getObjectByKey } from "@gala-chain/chaincode";
17
17
  import Decimal from "decimal.js";
18
18
 
19
19
  import { LaunchpadFeeConfig, LaunchpadSale, SaleStatus } from "../../api/types";
@@ -35,6 +35,18 @@ export async function fetchAndValidateSale(
35
35
  if (sale === undefined) {
36
36
  throw new NotFoundError("Sale record not found.");
37
37
  }
38
+
39
+ if (sale.saleStatus === SaleStatus.UPCOMING) {
40
+ if (sale.saleStartTime !== undefined && sale.saleStartTime > 0 && sale.saleStartTime < ctx.txUnixTime) {
41
+ sale.saleStatus = SaleStatus.ONGOING;
42
+ } else {
43
+ throw new DefaultError(
44
+ `Upcoming: This sale is coming soon. ` +
45
+ `${sale.saleStartTime ? "Sale starts at: " + sale.saleStartTime + " Unix time." : "Start time TBD."}`
46
+ );
47
+ }
48
+ }
49
+
38
50
  if (sale.saleStatus === SaleStatus.END) {
39
51
  throw new DefaultError("This sale has already ended.");
40
52
  }
@@ -66,3 +78,15 @@ export async function fetchLaunchpadFeeAddress(
66
78
 
67
79
  return platformFeeAddress;
68
80
  }
81
+
82
+ export async function fetchTokenDecimals(
83
+ ctx: GalaChainContext,
84
+ sale: LaunchpadSale
85
+ ): Promise<{ sellingTokenDecimals: number; nativeTokenDecimals: number }> {
86
+ const sellingToken = await fetchTokenClass(ctx, sale.fetchSellingTokenInstanceKey());
87
+ const nativeToken = await fetchTokenClass(ctx, sale.fetchNativeTokenInstanceKey());
88
+ return {
89
+ sellingTokenDecimals: sellingToken.decimals,
90
+ nativeTokenDecimals: nativeToken.decimals
91
+ };
92
+ }
package/src/cli.ts CHANGED
@@ -19,6 +19,8 @@ import type { ContractAPI } from "@gala-chain/api";
19
19
  import type { GalaContract } from "@gala-chain/chaincode";
20
20
  import "fabric-shim/cli";
21
21
  import fs from "fs";
22
+ import os from "os";
23
+ import path from "path";
22
24
 
23
25
  const [, , customCommand] = process.argv;
24
26
  if (customCommand === "get-contract-names") {
@@ -27,7 +29,7 @@ if (customCommand === "get-contract-names") {
27
29
  }
28
30
 
29
31
  if (customCommand === "get-contract-api") {
30
- saveContractAPI("/tmp/contract-api.json");
32
+ saveContractAPI(path.join(os.tmpdir(), "contract-api.json")); // output is stored at the operating system's default directory
31
33
  process.exit(0);
32
34
  }
33
35