@gala-chain/launchpad 1.0.0

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 (200) hide show
  1. package/.dev-env +7 -0
  2. package/.dockerignore +9 -0
  3. package/.eslintignore +4 -0
  4. package/.eslintrc.json +37 -0
  5. package/.github/workflows/publish-on-tag.yml +72 -0
  6. package/.github/workflows/test-on-push.yml +32 -0
  7. package/.nvmrc +1 -0
  8. package/.prettierignore +4 -0
  9. package/.prettierrc +12 -0
  10. package/Dockerfile +31 -0
  11. package/LICENSE +201 -0
  12. package/README.md +2 -0
  13. package/api-config.json +16 -0
  14. package/e2e/__snapshots__/api.spec.ts.snap +2482 -0
  15. package/e2e/api-config.json +17 -0
  16. package/e2e/api.spec.ts +48 -0
  17. package/e2e/jest.config.js +42 -0
  18. package/e2e/tsconfig.json +10 -0
  19. package/jest.config.ts +27 -0
  20. package/lib/jest.config.d.ts +13 -0
  21. package/lib/jest.config.d.ts.map +1 -0
  22. package/lib/jest.config.js +28 -0
  23. package/lib/jest.config.js.map +1 -0
  24. package/lib/package.json +54 -0
  25. package/lib/src/api/index.d.ts +4 -0
  26. package/lib/src/api/index.d.ts.map +1 -0
  27. package/lib/src/api/index.js +21 -0
  28. package/lib/src/api/index.js.map +1 -0
  29. package/lib/src/api/types/LaunchpadDtos.d.ts +102 -0
  30. package/lib/src/api/types/LaunchpadDtos.d.ts.map +1 -0
  31. package/lib/src/api/types/LaunchpadDtos.js +410 -0
  32. package/lib/src/api/types/LaunchpadDtos.js.map +1 -0
  33. package/lib/src/api/types/LaunchpadFeeConfig.d.ts +9 -0
  34. package/lib/src/api/types/LaunchpadFeeConfig.d.ts.map +1 -0
  35. package/lib/src/api/types/LaunchpadFeeConfig.js +56 -0
  36. package/lib/src/api/types/LaunchpadFeeConfig.js.map +1 -0
  37. package/lib/src/api/types/LaunchpadFinalizeAllocation.d.ts +10 -0
  38. package/lib/src/api/types/LaunchpadFinalizeAllocation.d.ts.map +1 -0
  39. package/lib/src/api/types/LaunchpadFinalizeAllocation.js +70 -0
  40. package/lib/src/api/types/LaunchpadFinalizeAllocation.js.map +1 -0
  41. package/lib/src/api/types/LaunchpadSale.d.ts +35 -0
  42. package/lib/src/api/types/LaunchpadSale.d.ts.map +1 -0
  43. package/lib/src/api/types/LaunchpadSale.js +195 -0
  44. package/lib/src/api/types/LaunchpadSale.js.map +1 -0
  45. package/lib/src/api/types/index.d.ts +5 -0
  46. package/lib/src/api/types/index.d.ts.map +1 -0
  47. package/lib/src/api/types/index.js +22 -0
  48. package/lib/src/api/types/index.js.map +1 -0
  49. package/lib/src/api/utils/error.d.ts +20 -0
  50. package/lib/src/api/utils/error.d.ts.map +1 -0
  51. package/lib/src/api/utils/error.js +35 -0
  52. package/lib/src/api/utils/error.js.map +1 -0
  53. package/lib/src/api/utils/index.d.ts +2 -0
  54. package/lib/src/api/utils/index.d.ts.map +1 -0
  55. package/lib/src/api/utils/index.js +19 -0
  56. package/lib/src/api/utils/index.js.map +1 -0
  57. package/lib/src/api/validators/decorators.d.ts +19 -0
  58. package/lib/src/api/validators/decorators.d.ts.map +1 -0
  59. package/lib/src/api/validators/decorators.js +391 -0
  60. package/lib/src/api/validators/decorators.js.map +1 -0
  61. package/lib/src/api/validators/index.d.ts +2 -0
  62. package/lib/src/api/validators/index.d.ts.map +1 -0
  63. package/lib/src/api/validators/index.js +19 -0
  64. package/lib/src/api/validators/index.js.map +1 -0
  65. package/lib/src/chaincode/LaunchpadContract.d.ts +20 -0
  66. package/lib/src/chaincode/LaunchpadContract.d.ts.map +1 -0
  67. package/lib/src/chaincode/LaunchpadContract.js +217 -0
  68. package/lib/src/chaincode/LaunchpadContract.js.map +1 -0
  69. package/lib/src/chaincode/dexLaunchpadFeeGate.d.ts +14 -0
  70. package/lib/src/chaincode/dexLaunchpadFeeGate.d.ts.map +1 -0
  71. package/lib/src/chaincode/dexLaunchpadFeeGate.js +47 -0
  72. package/lib/src/chaincode/dexLaunchpadFeeGate.js.map +1 -0
  73. package/lib/src/chaincode/index.d.ts +2 -0
  74. package/lib/src/chaincode/index.d.ts.map +1 -0
  75. package/lib/src/chaincode/index.js +19 -0
  76. package/lib/src/chaincode/index.js.map +1 -0
  77. package/lib/src/chaincode/launchpad/buyExactToken.d.ts +20 -0
  78. package/lib/src/chaincode/launchpad/buyExactToken.d.ts.map +1 -0
  79. package/lib/src/chaincode/launchpad/buyExactToken.js +113 -0
  80. package/lib/src/chaincode/launchpad/buyExactToken.js.map +1 -0
  81. package/lib/src/chaincode/launchpad/buyWithNative.d.ts +22 -0
  82. package/lib/src/chaincode/launchpad/buyWithNative.d.ts.map +1 -0
  83. package/lib/src/chaincode/launchpad/buyWithNative.js +106 -0
  84. package/lib/src/chaincode/launchpad/buyWithNative.js.map +1 -0
  85. package/lib/src/chaincode/launchpad/callMemeTokenIn.d.ts +27 -0
  86. package/lib/src/chaincode/launchpad/callMemeTokenIn.d.ts.map +1 -0
  87. package/lib/src/chaincode/launchpad/callMemeTokenIn.js +76 -0
  88. package/lib/src/chaincode/launchpad/callMemeTokenIn.js.map +1 -0
  89. package/lib/src/chaincode/launchpad/callMemeTokenOut.d.ts +25 -0
  90. package/lib/src/chaincode/launchpad/callMemeTokenOut.d.ts.map +1 -0
  91. package/lib/src/chaincode/launchpad/callMemeTokenOut.js +56 -0
  92. package/lib/src/chaincode/launchpad/callMemeTokenOut.js.map +1 -0
  93. package/lib/src/chaincode/launchpad/callNativeTokenIn.d.ts +25 -0
  94. package/lib/src/chaincode/launchpad/callNativeTokenIn.d.ts.map +1 -0
  95. package/lib/src/chaincode/launchpad/callNativeTokenIn.js +51 -0
  96. package/lib/src/chaincode/launchpad/callNativeTokenIn.js.map +1 -0
  97. package/lib/src/chaincode/launchpad/callNativeTokenOut.d.ts +26 -0
  98. package/lib/src/chaincode/launchpad/callNativeTokenOut.d.ts.map +1 -0
  99. package/lib/src/chaincode/launchpad/callNativeTokenOut.js +60 -0
  100. package/lib/src/chaincode/launchpad/callNativeTokenOut.js.map +1 -0
  101. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.d.ts +4 -0
  102. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.d.ts.map +1 -0
  103. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.js +58 -0
  104. package/lib/src/chaincode/launchpad/configureLaunchpadFeeConfig.js.map +1 -0
  105. package/lib/src/chaincode/launchpad/createSale.d.ts +26 -0
  106. package/lib/src/chaincode/launchpad/createSale.d.ts.map +1 -0
  107. package/lib/src/chaincode/launchpad/createSale.js +129 -0
  108. package/lib/src/chaincode/launchpad/createSale.js.map +1 -0
  109. package/lib/src/chaincode/launchpad/fees.d.ts +6 -0
  110. package/lib/src/chaincode/launchpad/fees.d.ts.map +1 -0
  111. package/lib/src/chaincode/launchpad/fees.js +85 -0
  112. package/lib/src/chaincode/launchpad/fees.js.map +1 -0
  113. package/lib/src/chaincode/launchpad/fetchLaunchpadAdressConfig.d.ts +4 -0
  114. package/lib/src/chaincode/launchpad/fetchLaunchpadAdressConfig.d.ts.map +1 -0
  115. package/lib/src/chaincode/launchpad/fetchLaunchpadAdressConfig.js +36 -0
  116. package/lib/src/chaincode/launchpad/fetchLaunchpadAdressConfig.js.map +1 -0
  117. package/lib/src/chaincode/launchpad/fetchSaleDetails.d.ts +19 -0
  118. package/lib/src/chaincode/launchpad/fetchSaleDetails.d.ts.map +1 -0
  119. package/lib/src/chaincode/launchpad/fetchSaleDetails.js +49 -0
  120. package/lib/src/chaincode/launchpad/fetchSaleDetails.js.map +1 -0
  121. package/lib/src/chaincode/launchpad/finaliseSale.d.ts +4 -0
  122. package/lib/src/chaincode/launchpad/finaliseSale.d.ts.map +1 -0
  123. package/lib/src/chaincode/launchpad/finaliseSale.js +144 -0
  124. package/lib/src/chaincode/launchpad/finaliseSale.js.map +1 -0
  125. package/lib/src/chaincode/launchpad/finalizeTokenAllocation.d.ts +4 -0
  126. package/lib/src/chaincode/launchpad/finalizeTokenAllocation.d.ts.map +1 -0
  127. package/lib/src/chaincode/launchpad/finalizeTokenAllocation.js +43 -0
  128. package/lib/src/chaincode/launchpad/finalizeTokenAllocation.js.map +1 -0
  129. package/lib/src/chaincode/launchpad/index.d.ts +15 -0
  130. package/lib/src/chaincode/launchpad/index.d.ts.map +1 -0
  131. package/lib/src/chaincode/launchpad/index.js +32 -0
  132. package/lib/src/chaincode/launchpad/index.js.map +1 -0
  133. package/lib/src/chaincode/launchpad/preMintCalculation.d.ts +17 -0
  134. package/lib/src/chaincode/launchpad/preMintCalculation.d.ts.map +1 -0
  135. package/lib/src/chaincode/launchpad/preMintCalculation.js +56 -0
  136. package/lib/src/chaincode/launchpad/preMintCalculation.js.map +1 -0
  137. package/lib/src/chaincode/launchpad/sellExactToken.d.ts +22 -0
  138. package/lib/src/chaincode/launchpad/sellExactToken.d.ts.map +1 -0
  139. package/lib/src/chaincode/launchpad/sellExactToken.js +102 -0
  140. package/lib/src/chaincode/launchpad/sellExactToken.js.map +1 -0
  141. package/lib/src/chaincode/launchpad/sellWithNative.d.ts +23 -0
  142. package/lib/src/chaincode/launchpad/sellWithNative.d.ts.map +1 -0
  143. package/lib/src/chaincode/launchpad/sellWithNative.js +97 -0
  144. package/lib/src/chaincode/launchpad/sellWithNative.js.map +1 -0
  145. package/lib/src/chaincode/utils/index.d.ts +2 -0
  146. package/lib/src/chaincode/utils/index.d.ts.map +1 -0
  147. package/lib/src/chaincode/utils/index.js +19 -0
  148. package/lib/src/chaincode/utils/index.js.map +1 -0
  149. package/lib/src/chaincode/utils/launchpadSaleUtils.d.ts +11 -0
  150. package/lib/src/chaincode/utils/launchpadSaleUtils.d.ts.map +1 -0
  151. package/lib/src/chaincode/utils/launchpadSaleUtils.js +65 -0
  152. package/lib/src/chaincode/utils/launchpadSaleUtils.js.map +1 -0
  153. package/lib/src/cli.d.ts +3 -0
  154. package/lib/src/cli.d.ts.map +1 -0
  155. package/lib/src/cli.js +41 -0
  156. package/lib/src/cli.js.map +1 -0
  157. package/lib/src/index.d.ts +14 -0
  158. package/lib/src/index.d.ts.map +1 -0
  159. package/lib/src/index.js +32 -0
  160. package/lib/src/index.js.map +1 -0
  161. package/lib/tsconfig.tsbuildinfo +1 -0
  162. package/package.json +54 -0
  163. package/src/api/index.ts +18 -0
  164. package/src/api/types/LaunchpadDtos.ts +362 -0
  165. package/src/api/types/LaunchpadFeeConfig.ts +45 -0
  166. package/src/api/types/LaunchpadFinalizeAllocation.ts +65 -0
  167. package/src/api/types/LaunchpadSale.ts +200 -0
  168. package/src/api/types/index.ts +19 -0
  169. package/src/api/utils/error.ts +32 -0
  170. package/src/api/utils/index.ts +16 -0
  171. package/src/api/validators/decorators.spec.ts +277 -0
  172. package/src/api/validators/decorators.ts +401 -0
  173. package/src/api/validators/index.ts +16 -0
  174. package/src/chaincode/LaunchpadContract.ts +211 -0
  175. package/src/chaincode/dexLaunchpadFeeGate.ts +43 -0
  176. package/src/chaincode/index.ts +16 -0
  177. package/src/chaincode/launchpad/buyExactToken.ts +128 -0
  178. package/src/chaincode/launchpad/buyWithNative.ts +120 -0
  179. package/src/chaincode/launchpad/callMemeTokenIn.ts +82 -0
  180. package/src/chaincode/launchpad/callMemeTokenOut.ts +80 -0
  181. package/src/chaincode/launchpad/callNativeTokenIn.ts +71 -0
  182. package/src/chaincode/launchpad/callNativeTokenOut.ts +81 -0
  183. package/src/chaincode/launchpad/configureLaunchpadFeeConfig.ts +69 -0
  184. package/src/chaincode/launchpad/createSale.ts +157 -0
  185. package/src/chaincode/launchpad/fees.ts +105 -0
  186. package/src/chaincode/launchpad/fetchLaunchpadAdressConfig.ts +38 -0
  187. package/src/chaincode/launchpad/fetchSaleDetails.ts +53 -0
  188. package/src/chaincode/launchpad/finaliseSale.ts +217 -0
  189. package/src/chaincode/launchpad/finalizeTokenAllocation.ts +47 -0
  190. package/src/chaincode/launchpad/index.ts +28 -0
  191. package/src/chaincode/launchpad/preMintCalculation.ts +61 -0
  192. package/src/chaincode/launchpad/sellExactToken.ts +122 -0
  193. package/src/chaincode/launchpad/sellWithNative.ts +112 -0
  194. package/src/chaincode/utils/index.ts +15 -0
  195. package/src/chaincode/utils/launchpadSaleUtils.ts +68 -0
  196. package/src/cli.ts +63 -0
  197. package/src/index.ts +32 -0
  198. package/tsconfig.base.json +29 -0
  199. package/tsconfig.json +19 -0
  200. package/tsconfig.spec.json +11 -0
@@ -0,0 +1,61 @@
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 { BigNumber } from "bignumber.js";
16
+ import Decimal from "decimal.js";
17
+
18
+ import { LaunchpadSale, PreMintCalculationDto } from "../../api/types";
19
+ import { getBondingConstants } from "../utils";
20
+
21
+ BigNumber.config({
22
+ ROUNDING_MODE: BigNumber.ROUND_UP
23
+ });
24
+
25
+ /**
26
+ * Calculates the number of tokens that can be purchased using a specified amount
27
+ * of native tokens based on a bonding curve mechanism.
28
+ *
29
+ * This function applies the bonding curve formula for a brand new sale with zero tokens sold
30
+ * to determine the number of tokens the user can buy with the provided native token amount.
31
+ *
32
+ * @param buyTokenDTO - The Amount of native tokens to spend for the purchase.
33
+ *
34
+ * @returns A promise that resolves to a string representing the calculated amount of
35
+ * tokens to be received, rounded down to 18 decimal places.
36
+ *
37
+ * @throws Error if the calculation results in an invalid state.
38
+ */
39
+ export async function calculatePreMintTokens(buyTokenDTO: PreMintCalculationDto): Promise<string> {
40
+ const totalTokensSold = new Decimal(0); // current tokens sold / x
41
+ const nativeTokens = new Decimal(buyTokenDTO.nativeTokenQuantity.toString()); // native tokens used to buy / y
42
+ const basePrice = new Decimal(LaunchpadSale.BASE_PRICE); // base price / a
43
+ const { exponentFactor, euler, decimals } = getBondingConstants();
44
+
45
+ const constant = nativeTokens.mul(exponentFactor).div(basePrice);
46
+
47
+ const exponent1 = exponentFactor.mul(totalTokensSold).div(decimals);
48
+
49
+ const eResult1 = euler.pow(exponent1);
50
+
51
+ const ethScaled = constant.add(eResult1);
52
+
53
+ const lnEthScaled = ethScaled.ln().mul(decimals);
54
+
55
+ const lnEthScaledBase = lnEthScaled.div(exponentFactor);
56
+
57
+ const result = lnEthScaledBase.minus(totalTokensSold);
58
+ const roundedResult = result.toDecimalPlaces(18, Decimal.ROUND_DOWN);
59
+
60
+ return roundedResult.toString();
61
+ }
@@ -0,0 +1,122 @@
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 { GalaChainContext, fetchTokenClass, putChainObject, transferToken } from "@gala-chain/chaincode";
16
+ import { BigNumber } from "bignumber.js";
17
+
18
+ import { ExactTokenQuantityDto, NativeTokenQuantityDto, TradeResDto } from "../../api/types";
19
+ import { SlippageToleranceExceededError } from "../../api/utils/error";
20
+ import { fetchAndValidateSale } from "../utils";
21
+ import { callMemeTokenIn } from "./callMemeTokenIn";
22
+ import { callNativeTokenOut } from "./callNativeTokenOut";
23
+ import { payReverseBondingCurveFee } from "./fees";
24
+
25
+ BigNumber.config({
26
+ ROUNDING_MODE: BigNumber.ROUND_UP
27
+ });
28
+
29
+ /**
30
+ * Executes the sale of an exact amount of tokens for native tokens (e.g., GALA).
31
+ *
32
+ * This function facilitates selling a specific token amount by transferring the tokens to
33
+ * the sale vault and providing the calculated native tokens in return. It ensures validation
34
+ * of the sale, handles insufficient vault balances, and checks expected vs. actual native tokens.
35
+ *
36
+ * @param ctx - The context object providing access to the GalaChain environment.
37
+ * @param sellTokenDTO - An object containing the sale details:
38
+ * - `vaultAddress`: The address of the sale.
39
+ * - `tokenAmount`: The exact amount of tokens to sell.
40
+ * - `expectedNativeToken` (optional): The expected amount of native tokens in return.
41
+ *
42
+ * @returns A promise that resolves to a `TradeResDto` object containing the updated
43
+ * balances of the seller's tokens and native tokens.
44
+ *
45
+ * @throws DefaultError if the expected native tokens exceed the actual amount to be provided.
46
+ */
47
+ export async function sellExactToken(
48
+ ctx: GalaChainContext,
49
+ sellTokenDTO: ExactTokenQuantityDto
50
+ ): Promise<TradeResDto> {
51
+ const sale = await fetchAndValidateSale(ctx, sellTokenDTO.vaultAddress);
52
+
53
+ const callNativeTokenOutResult = await callNativeTokenOut(ctx, sellTokenDTO);
54
+ let nativeTokensToProvide = new BigNumber(callNativeTokenOutResult.calculatedQuantity);
55
+ const nativeTokensLeftInVault = new BigNumber(sale.nativeTokenQuantity);
56
+ const nativeToken = sale.fetchNativeTokenInstanceKey();
57
+ const memeToken = sale.fetchSellingTokenInstanceKey();
58
+
59
+ if (nativeTokensLeftInVault.comparedTo(nativeTokensToProvide) < 0) {
60
+ nativeTokensToProvide = nativeTokensLeftInVault;
61
+ const nativeTokensBeingSoldDto = new NativeTokenQuantityDto(
62
+ sellTokenDTO.vaultAddress,
63
+ nativeTokensToProvide
64
+ );
65
+ const callMemeTokenInResult = await callMemeTokenIn(ctx, nativeTokensBeingSoldDto);
66
+ sellTokenDTO.tokenQuantity = new BigNumber(callMemeTokenInResult.calculatedQuantity);
67
+ }
68
+
69
+ if (
70
+ sellTokenDTO.expectedNativeToken &&
71
+ sellTokenDTO.expectedNativeToken.comparedTo(nativeTokensToProvide) > 0
72
+ ) {
73
+ throw new SlippageToleranceExceededError(
74
+ "Expected Gala tokens from this operation exceeds the actual amount that will be provided."
75
+ );
76
+ }
77
+
78
+ // The fee must be paid BEFORE the sale can happen.
79
+ // That means you cannot pay the fee using proceeds from the sale.
80
+ await payReverseBondingCurveFee(
81
+ ctx,
82
+ sale,
83
+ nativeTokensToProvide,
84
+ sellTokenDTO.extraFees?.maxAcceptableReverseBondingCurveFee
85
+ );
86
+
87
+ await transferToken(ctx, {
88
+ from: ctx.callingUser,
89
+ to: sellTokenDTO.vaultAddress,
90
+ tokenInstanceKey: memeToken,
91
+ quantity: sellTokenDTO.tokenQuantity,
92
+ allowancesToUse: [],
93
+ authorizedOnBehalf: undefined
94
+ });
95
+
96
+ await transferToken(ctx, {
97
+ from: sellTokenDTO.vaultAddress,
98
+ to: ctx.callingUser,
99
+ tokenInstanceKey: nativeToken,
100
+ quantity: nativeTokensToProvide,
101
+ allowancesToUse: [],
102
+ authorizedOnBehalf: {
103
+ callingOnBehalf: sellTokenDTO.vaultAddress,
104
+ callingUser: ctx.callingUser
105
+ }
106
+ });
107
+
108
+ sale.sellToken(sellTokenDTO.tokenQuantity, nativeTokensToProvide);
109
+ await putChainObject(ctx, sale);
110
+
111
+ const token = await fetchTokenClass(ctx, sale.sellingToken);
112
+ return {
113
+ inputQuantity: sellTokenDTO.tokenQuantity.toFixed(),
114
+ outputQuantity: nativeTokensToProvide.toFixed(),
115
+ tokenName: token.name,
116
+ tradeType: "Sell",
117
+ vaultAddress: sellTokenDTO.vaultAddress,
118
+ userAddress: ctx.callingUser,
119
+ isFinalized: false,
120
+ functionName: "SellExactToken"
121
+ };
122
+ }
@@ -0,0 +1,112 @@
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 { GalaChainContext, fetchTokenClass, putChainObject, transferToken } from "@gala-chain/chaincode";
16
+ import { BigNumber } from "bignumber.js";
17
+
18
+ import { NativeTokenQuantityDto, TradeResDto } from "../../api/types";
19
+ import { SlippageToleranceExceededError } from "../../api/utils/error";
20
+ import { fetchAndValidateSale } from "../utils";
21
+ import { callMemeTokenIn } from "./callMemeTokenIn";
22
+ import { payReverseBondingCurveFee } from "./fees";
23
+
24
+ BigNumber.config({
25
+ ROUNDING_MODE: BigNumber.ROUND_UP
26
+ });
27
+
28
+ /**
29
+ * Executes a sale of tokens using native tokens (e.g., GALA) in exchange for the specified token amount.
30
+ *
31
+ * This function handles the process of selling tokens for native tokens in the sale vault, ensuring
32
+ * that the token amount and native token quantity are properly adjusted based on the sale vault's
33
+ * available balance. It also checks if the expected token amount matches the actual amount required.
34
+ *
35
+ * @param ctx - The context object that provides access to the GalaChain environment.
36
+ * @param sellTokenDTO - An object containing the sale details:
37
+ * - `vaultAddress`: The address of the sale.
38
+ * - `nativeTokenAmount`: The amount of native tokens to be used in the sale.
39
+ * - `expectedToken` (optional): The expected amount of tokens to be received in return.
40
+ *
41
+ * @returns A promise that resolves to a `TradeResDto` object containing the updated
42
+ * balances of the seller's tokens and native tokens.
43
+ *
44
+ * @throws DefaultError if the expected token amount is less than the actual amount required
45
+ * for the operation.
46
+ */
47
+ export async function sellWithNative(
48
+ ctx: GalaChainContext,
49
+ sellTokenDTO: NativeTokenQuantityDto
50
+ ): Promise<TradeResDto> {
51
+ const sale = await fetchAndValidateSale(ctx, sellTokenDTO.vaultAddress);
52
+
53
+ const nativeTokensLeftInVault = new BigNumber(sale.nativeTokenQuantity);
54
+ if (nativeTokensLeftInVault.comparedTo(sellTokenDTO.nativeTokenQuantity) < 0) {
55
+ sellTokenDTO.nativeTokenQuantity = nativeTokensLeftInVault;
56
+ }
57
+
58
+ const callMemeTokenInResult = await callMemeTokenIn(ctx, sellTokenDTO);
59
+ const tokensToSell = new BigNumber(callMemeTokenInResult.calculatedQuantity);
60
+ const nativeToken = sale.fetchNativeTokenInstanceKey();
61
+ const memeToken = sale.fetchSellingTokenInstanceKey();
62
+
63
+ if (sellTokenDTO.expectedToken && sellTokenDTO.expectedToken.comparedTo(tokensToSell) < 0) {
64
+ throw new SlippageToleranceExceededError(
65
+ "Token amount expected to cost for this operation is less than the the actual amount required."
66
+ );
67
+ }
68
+
69
+ // The fee must be paid BEFORE the sale can happen.
70
+ // That means you cannot pay the fee using proceeds from the sale.
71
+ await payReverseBondingCurveFee(
72
+ ctx,
73
+ sale,
74
+ sellTokenDTO.nativeTokenQuantity,
75
+ sellTokenDTO.extraFees?.maxAcceptableReverseBondingCurveFee
76
+ );
77
+
78
+ await transferToken(ctx, {
79
+ from: ctx.callingUser,
80
+ to: sellTokenDTO.vaultAddress,
81
+ tokenInstanceKey: memeToken,
82
+ quantity: tokensToSell,
83
+ allowancesToUse: [],
84
+ authorizedOnBehalf: undefined
85
+ });
86
+ await transferToken(ctx, {
87
+ from: sellTokenDTO.vaultAddress,
88
+ to: ctx.callingUser,
89
+ tokenInstanceKey: nativeToken,
90
+ quantity: sellTokenDTO.nativeTokenQuantity,
91
+ allowancesToUse: [],
92
+ authorizedOnBehalf: {
93
+ callingOnBehalf: sellTokenDTO.vaultAddress,
94
+ callingUser: ctx.callingUser
95
+ }
96
+ });
97
+
98
+ sale.sellToken(tokensToSell, sellTokenDTO.nativeTokenQuantity);
99
+ await putChainObject(ctx, sale);
100
+
101
+ const token = await fetchTokenClass(ctx, sale.sellingToken);
102
+ return {
103
+ inputQuantity: tokensToSell.toFixed(),
104
+ outputQuantity: sellTokenDTO.nativeTokenQuantity.toFixed(),
105
+ tokenName: token.name,
106
+ tradeType: "Sell",
107
+ vaultAddress: sellTokenDTO.vaultAddress,
108
+ userAddress: ctx.callingUser,
109
+ isFinalized: false,
110
+ functionName: "SellWithNative"
111
+ };
112
+ }
@@ -0,0 +1,15 @@
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
+ export * from "./launchpadSaleUtils";
@@ -0,0 +1,68 @@
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 { ChainError, DefaultError, ErrorCode, NotFoundError } from "@gala-chain/api";
16
+ import { GalaChainContext, getObjectByKey } from "@gala-chain/chaincode";
17
+ import Decimal from "decimal.js";
18
+
19
+ import { LaunchpadFeeConfig, LaunchpadSale, SaleStatus } from "../../api/types";
20
+
21
+ export async function fetchAndValidateSale(
22
+ ctx: GalaChainContext,
23
+ vaultAddress: string
24
+ ): Promise<LaunchpadSale> {
25
+ const key = ctx.stub.createCompositeKey(LaunchpadSale.INDEX_KEY, [vaultAddress]);
26
+ const sale = await getObjectByKey(ctx, LaunchpadSale, key).catch((e) => {
27
+ const chainError = ChainError.from(e);
28
+ if (chainError.matches(ErrorCode.NOT_FOUND)) {
29
+ return undefined;
30
+ } else {
31
+ throw chainError;
32
+ }
33
+ });
34
+
35
+ if (sale === undefined) {
36
+ throw new NotFoundError("Sale record not found.");
37
+ }
38
+ if (sale.saleStatus === SaleStatus.END) {
39
+ throw new DefaultError("This sale has already ended.");
40
+ }
41
+
42
+ return sale;
43
+ }
44
+
45
+ export function getBondingConstants() {
46
+ return {
47
+ exponentFactor: new Decimal("1166069000000"), // exponent factor / b
48
+ euler: new Decimal("2.7182818284590452353602874713527"), // e
49
+ decimals: new Decimal("1e+18") // scaling factor for decimals
50
+ };
51
+ }
52
+
53
+ export async function fetchLaunchpadFeeAddress(
54
+ ctx: GalaChainContext
55
+ ): Promise<LaunchpadFeeConfig | undefined> {
56
+ const key = ctx.stub.createCompositeKey(LaunchpadFeeConfig.INDEX_KEY, []);
57
+
58
+ const platformFeeAddress = await getObjectByKey(ctx, LaunchpadFeeConfig, key).catch((e) => {
59
+ const chainError = ChainError.from(e);
60
+ if (chainError.matches(ErrorCode.NOT_FOUND)) {
61
+ return undefined;
62
+ } else {
63
+ throw chainError;
64
+ }
65
+ });
66
+
67
+ return platformFeeAddress;
68
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+
3
+ /*
4
+ * Copyright (c) Gala Games Inc. All rights reserved.
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ // Import and run standard fabric-chaincode-node cli
18
+ import type { ContractAPI } from "@gala-chain/api";
19
+ import type { GalaContract } from "@gala-chain/chaincode";
20
+ import "fabric-shim/cli";
21
+ import fs from "fs";
22
+
23
+ const [, , customCommand] = process.argv;
24
+ if (customCommand === "get-contract-names") {
25
+ printContractNames();
26
+ process.exit(0);
27
+ }
28
+
29
+ if (customCommand === "get-contract-api") {
30
+ saveContractAPI("/tmp/contract-api.json");
31
+ process.exit(0);
32
+ }
33
+
34
+ function getContractInstances(): GalaContract[] {
35
+ // importing contracts would produce a lot of noise, so we set the log level to error
36
+ process.env.CORE_CHAINCODE_LOGGING_LEVEL = "error";
37
+ process.env.LOG_LEVEL = "error";
38
+
39
+ const { contracts } = require("./index");
40
+ return (contracts ?? [])
41
+ .filter((c: any) => typeof c === "function")
42
+ .map((Cls) => new Cls())
43
+ .filter((c: GalaContract) => typeof c.getName === "function");
44
+ }
45
+
46
+ function printContractNames() {
47
+ const response = getContractInstances()
48
+ .map((c) => c.getName())
49
+ .filter((name: string) => name !== undefined)
50
+ .sort()
51
+ .map((contractName: string) => ({ contractName }));
52
+
53
+ console.log(JSON.stringify(response));
54
+ }
55
+
56
+ function saveContractAPI(path: string) {
57
+ const response = getContractInstances()
58
+ .map((c) => c.getContractAPI())
59
+ .filter((api: ContractAPI) => api !== undefined)
60
+ .sort((a, b) => a.contractName.localeCompare(b.contractName));
61
+
62
+ fs.writeFileSync(path, JSON.stringify(response));
63
+ }
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ // sort-imports-ignore
2
+ /*
3
+ * Copyright (c) Gala Games Inc. All rights reserved.
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import "dotenv/config";
17
+
18
+ import { GalaContract, GalaJSONSerializer } from "@gala-chain/chaincode";
19
+
20
+ import { LaunchpadContract } from "./chaincode";
21
+
22
+ export const contracts: { new (): GalaContract }[] = [LaunchpadContract];
23
+
24
+ export * from "./chaincode";
25
+ export * from "./api";
26
+
27
+ export const serializers = {
28
+ transaction: "galaJsonSerializer",
29
+ serializers: {
30
+ galaJsonSerializer: GalaJSONSerializer
31
+ }
32
+ };
@@ -0,0 +1,29 @@
1
+ {
2
+ "compileOnSave": false,
3
+ "compilerOptions": {
4
+ "moduleDetection": "force",
5
+ "baseUrl": ".",
6
+ "rootDir": ".",
7
+ "module": "commonjs",
8
+ "moduleResolution": "node",
9
+ "resolveJsonModule": true,
10
+ "target": "ES2019",
11
+ "lib": ["ES2019"],
12
+ "emitDecoratorMetadata": true,
13
+ "experimentalDecorators": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true,
17
+ "importHelpers": true,
18
+ "esModuleInterop": true,
19
+ "strictNullChecks": true,
20
+ "composite": true,
21
+ "skipLibCheck": true,
22
+ "noPropertyAccessFromIndexSignature": false,
23
+ "strictPropertyInitialization": false
24
+ },
25
+ "exclude": ["node_modules"],
26
+ "include": [
27
+ "package.json"
28
+ ]
29
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "outDir": "lib",
6
+ "declarationDir": "lib",
7
+ "composite": true,
8
+ "declarationMap": true,
9
+ "sourceMap": true
10
+ },
11
+ "files": [],
12
+ "include": ["**/*", "package.json"],
13
+ "exclude": ["lib", "**/*spec.ts", "src/__mocks__", "src/__test__"],
14
+ "references": [
15
+ {
16
+ "path": "./tsconfig.spec.json"
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "types": ["jest", "node"],
7
+ "declarationMap": true,
8
+ "sourceMap": true
9
+ },
10
+ "include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
11
+ }