@gala-chain/launchpad 1.0.8 → 1.0.10
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.
- package/CLAUDE.md +279 -0
- package/lib/package.json +2 -2
- package/lib/src/chaincode/launchpad/buyExactToken.js +1 -1
- package/lib/src/chaincode/launchpad/buyExactToken.js.map +1 -1
- package/lib/src/chaincode/launchpad/buyWithNative.d.ts.map +1 -1
- package/lib/src/chaincode/launchpad/buyWithNative.js +11 -4
- package/lib/src/chaincode/launchpad/buyWithNative.js.map +1 -1
- package/lib/src/chaincode/launchpad/finaliseSale.js +1 -1
- package/lib/src/chaincode/launchpad/finaliseSale.js.map +1 -1
- package/lib/src/chaincode/launchpad/sellWithNative.d.ts.map +1 -1
- package/lib/src/chaincode/launchpad/sellWithNative.js +9 -1
- package/lib/src/chaincode/launchpad/sellWithNative.js.map +1 -1
- package/lib/src/chaincode/test/launchpadgala.js +1 -1
- package/lib/src/chaincode/test/launchpadgala.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/chaincode/launchpad/buyExactToken.spec.ts +140 -20
- package/src/chaincode/launchpad/buyExactToken.ts +1 -1
- package/src/chaincode/launchpad/buyWithNative.spec.ts +99 -25
- package/src/chaincode/launchpad/buyWithNative.ts +20 -5
- package/src/chaincode/launchpad/callMemeTokenIn.spec.ts +244 -0
- package/src/chaincode/launchpad/callMemeTokenOut.spec.ts +1 -1
- package/src/chaincode/launchpad/callNativeTokenIn.spec.ts +269 -0
- package/src/chaincode/launchpad/callNativeTokenOut.spec.ts +276 -0
- package/src/chaincode/launchpad/configureLaunchpadFeeConfig.spec.ts +202 -0
- package/src/chaincode/launchpad/createSale.spec.ts +259 -0
- package/src/chaincode/launchpad/fetchSaleDetails.spec.ts +141 -0
- package/src/chaincode/launchpad/finaliseSale.ts +1 -1
- package/src/chaincode/launchpad/finalizeTokenAllocation.spec.ts +126 -0
- package/src/chaincode/launchpad/sellExactToken.spec.ts +284 -0
- package/src/chaincode/launchpad/sellWithNative.spec.ts +329 -0
- package/src/chaincode/launchpad/sellWithNative.ts +22 -5
- package/src/chaincode/test/launchpadgala.ts +1 -1
|
@@ -0,0 +1,259 @@
|
|
|
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 { TokenBalance, TokenClass, TokenInstance, randomUniqueKey } from "@gala-chain/api";
|
|
16
|
+
import { currency, fixture, users } from "@gala-chain/test";
|
|
17
|
+
import BigNumber from "bignumber.js";
|
|
18
|
+
import { plainToInstance } from "class-transformer";
|
|
19
|
+
|
|
20
|
+
import { CreateTokenSaleDTO } from "../../api/types";
|
|
21
|
+
import { LaunchpadContract } from "../LaunchpadContract";
|
|
22
|
+
|
|
23
|
+
describe("createSale", () => {
|
|
24
|
+
it("should create a new token sale successfully", async () => {
|
|
25
|
+
// Given
|
|
26
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1);
|
|
27
|
+
|
|
28
|
+
const createSaleDto = new CreateTokenSaleDTO(
|
|
29
|
+
"Test Token",
|
|
30
|
+
"TEST",
|
|
31
|
+
"A test token for launchpad",
|
|
32
|
+
"https://example.com/token.png",
|
|
33
|
+
new BigNumber(0),
|
|
34
|
+
"TestCollection",
|
|
35
|
+
"TestCategory"
|
|
36
|
+
);
|
|
37
|
+
createSaleDto.websiteUrl = "https://example.com";
|
|
38
|
+
createSaleDto.uniqueKey = randomUniqueKey();
|
|
39
|
+
|
|
40
|
+
const signedDto = createSaleDto.signed(users.testUser1.privateKey);
|
|
41
|
+
|
|
42
|
+
// When
|
|
43
|
+
const response = await contract.CreateSale(ctx, signedDto);
|
|
44
|
+
|
|
45
|
+
// Then
|
|
46
|
+
expect(response.Status).toBe(1);
|
|
47
|
+
expect(response.Data?.tokenName).toBe("Test Token");
|
|
48
|
+
expect(response.Data?.symbol).toBe("TEST");
|
|
49
|
+
expect(response.Data?.description).toBe("A test token for launchpad");
|
|
50
|
+
expect(response.Data?.collection).toBe("TestCollection");
|
|
51
|
+
expect(response.Data?.category).toBe("TestCategory");
|
|
52
|
+
expect(response.Data?.vaultAddress).toBeDefined();
|
|
53
|
+
expect(response.Data?.creatorAddress).toBe(users.testUser1.identityKey);
|
|
54
|
+
expect(response.Data?.isFinalized).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should create token sale with telegram URL", async () => {
|
|
58
|
+
// Given
|
|
59
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1);
|
|
60
|
+
|
|
61
|
+
const createSaleDto = new CreateTokenSaleDTO(
|
|
62
|
+
"Telegram Token",
|
|
63
|
+
"TG",
|
|
64
|
+
"A token with telegram link",
|
|
65
|
+
"https://example.com/tg.png",
|
|
66
|
+
new BigNumber(0),
|
|
67
|
+
"TelegramCollection",
|
|
68
|
+
"SocialCategory"
|
|
69
|
+
);
|
|
70
|
+
createSaleDto.telegramUrl = "https://t.me/testtoken";
|
|
71
|
+
createSaleDto.uniqueKey = randomUniqueKey();
|
|
72
|
+
|
|
73
|
+
const signedDto = createSaleDto.signed(users.testUser1.privateKey);
|
|
74
|
+
|
|
75
|
+
// When
|
|
76
|
+
const response = await contract.CreateSale(ctx, signedDto);
|
|
77
|
+
|
|
78
|
+
// Then
|
|
79
|
+
expect(response.Status).toBe(1);
|
|
80
|
+
expect(response.Data?.telegramUrl).toBe("https://t.me/testtoken");
|
|
81
|
+
expect(response.Data?.websiteUrl).toBe("");
|
|
82
|
+
expect(response.Data?.twitterUrl).toBe("");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should create token sale with twitter URL", async () => {
|
|
86
|
+
// Given
|
|
87
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1);
|
|
88
|
+
|
|
89
|
+
const createSaleDto = new CreateTokenSaleDTO(
|
|
90
|
+
"Twitter Token",
|
|
91
|
+
"TWT",
|
|
92
|
+
"A token with twitter link",
|
|
93
|
+
"https://example.com/twt.png",
|
|
94
|
+
new BigNumber(0),
|
|
95
|
+
"TwitterCollection",
|
|
96
|
+
"SocialCategory"
|
|
97
|
+
);
|
|
98
|
+
createSaleDto.twitterUrl = "https://twitter.com/testtoken";
|
|
99
|
+
createSaleDto.uniqueKey = randomUniqueKey();
|
|
100
|
+
|
|
101
|
+
const signedDto = createSaleDto.signed(users.testUser1.privateKey);
|
|
102
|
+
|
|
103
|
+
// When
|
|
104
|
+
const response = await contract.CreateSale(ctx, signedDto);
|
|
105
|
+
|
|
106
|
+
// Then
|
|
107
|
+
expect(response.Status).toBe(1);
|
|
108
|
+
expect(response.Data?.twitterUrl).toBe("https://twitter.com/testtoken");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should create token sale with pre-buy amount", async () => {
|
|
112
|
+
// Given - Setup GALA token for pre-buy (matching LaunchpadSale nativeToken)
|
|
113
|
+
const galaClass = plainToInstance(TokenClass, {
|
|
114
|
+
collection: "GALA",
|
|
115
|
+
category: "Unit",
|
|
116
|
+
type: "none",
|
|
117
|
+
additionalKey: "none",
|
|
118
|
+
decimals: 8,
|
|
119
|
+
name: "GALA",
|
|
120
|
+
symbol: "GALA",
|
|
121
|
+
description: "GALA token",
|
|
122
|
+
image: "",
|
|
123
|
+
maxSupply: new BigNumber("1e+10"),
|
|
124
|
+
maxCapacity: new BigNumber("1e+10"),
|
|
125
|
+
totalMintAllowance: new BigNumber("1e+10"),
|
|
126
|
+
totalSupply: new BigNumber("1e+10"),
|
|
127
|
+
totalBurned: new BigNumber("0"),
|
|
128
|
+
authorities: [users.testUser1.identityKey]
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const galaInstance = plainToInstance(TokenInstance, {
|
|
132
|
+
collection: "GALA",
|
|
133
|
+
category: "Unit",
|
|
134
|
+
type: "none",
|
|
135
|
+
additionalKey: "none",
|
|
136
|
+
instance: new BigNumber(0),
|
|
137
|
+
isNonFungible: false,
|
|
138
|
+
owner: users.testUser1.identityKey,
|
|
139
|
+
quantity: new BigNumber("1e+10")
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const userGalaBalance = plainToInstance(TokenBalance, {
|
|
143
|
+
collection: "GALA",
|
|
144
|
+
category: "Unit",
|
|
145
|
+
type: "none",
|
|
146
|
+
additionalKey: "none",
|
|
147
|
+
instance: new BigNumber(0),
|
|
148
|
+
owner: users.testUser1.identityKey,
|
|
149
|
+
quantity: new BigNumber("1000") // User has GALA for pre-buy
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
153
|
+
.registeredUsers(users.testUser1)
|
|
154
|
+
.savedState(galaClass, galaInstance, userGalaBalance);
|
|
155
|
+
|
|
156
|
+
const createSaleDto = new CreateTokenSaleDTO(
|
|
157
|
+
"Pre-buy Token",
|
|
158
|
+
"PRE",
|
|
159
|
+
"A token with pre-buy",
|
|
160
|
+
"https://example.com/pre.png",
|
|
161
|
+
new BigNumber("10"),
|
|
162
|
+
"PreBuyCollection",
|
|
163
|
+
"PreBuyCategory"
|
|
164
|
+
);
|
|
165
|
+
createSaleDto.websiteUrl = "https://example.com";
|
|
166
|
+
createSaleDto.uniqueKey = randomUniqueKey();
|
|
167
|
+
|
|
168
|
+
const signedDto = createSaleDto.signed(users.testUser1.privateKey);
|
|
169
|
+
|
|
170
|
+
// When
|
|
171
|
+
const response = await contract.CreateSale(ctx, signedDto);
|
|
172
|
+
|
|
173
|
+
// Then
|
|
174
|
+
expect(response.Status).toBe(1);
|
|
175
|
+
expect(response.Data?.initialBuyQuantity).toBe("10");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("should convert token symbol to uppercase", async () => {
|
|
179
|
+
// Given
|
|
180
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1);
|
|
181
|
+
|
|
182
|
+
const createSaleDto = new CreateTokenSaleDTO(
|
|
183
|
+
"Lowercase Token",
|
|
184
|
+
"lower", // lowercase symbol
|
|
185
|
+
"A token with lowercase symbol",
|
|
186
|
+
"https://example.com/lower.png",
|
|
187
|
+
new BigNumber(0),
|
|
188
|
+
"LowerCollection",
|
|
189
|
+
"LowerCategory"
|
|
190
|
+
);
|
|
191
|
+
createSaleDto.websiteUrl = "https://example.com";
|
|
192
|
+
createSaleDto.uniqueKey = randomUniqueKey();
|
|
193
|
+
|
|
194
|
+
const signedDto = createSaleDto.signed(users.testUser1.privateKey);
|
|
195
|
+
|
|
196
|
+
// When
|
|
197
|
+
const response = await contract.CreateSale(ctx, signedDto);
|
|
198
|
+
|
|
199
|
+
// Then
|
|
200
|
+
expect(response.Status).toBe(1);
|
|
201
|
+
expect(response.Data?.symbol).toBe("LOWER"); // Should be converted to uppercase
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("should create sale with all social media URLs", async () => {
|
|
205
|
+
// Given
|
|
206
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1);
|
|
207
|
+
|
|
208
|
+
const createSaleDto = new CreateTokenSaleDTO(
|
|
209
|
+
"Social Token",
|
|
210
|
+
"SOC",
|
|
211
|
+
"A fully connected social token",
|
|
212
|
+
"https://example.com/soc.png",
|
|
213
|
+
new BigNumber(0),
|
|
214
|
+
"SocialCollection",
|
|
215
|
+
"FullSocialCategory"
|
|
216
|
+
);
|
|
217
|
+
createSaleDto.websiteUrl = "https://socialtoken.com";
|
|
218
|
+
createSaleDto.telegramUrl = "https://t.me/socialtoken";
|
|
219
|
+
createSaleDto.twitterUrl = "https://twitter.com/socialtoken";
|
|
220
|
+
createSaleDto.uniqueKey = randomUniqueKey();
|
|
221
|
+
|
|
222
|
+
const signedDto = createSaleDto.signed(users.testUser1.privateKey);
|
|
223
|
+
|
|
224
|
+
// When
|
|
225
|
+
const response = await contract.CreateSale(ctx, signedDto);
|
|
226
|
+
|
|
227
|
+
// Then
|
|
228
|
+
expect(response.Status).toBe(1);
|
|
229
|
+
expect(response.Data?.websiteUrl).toBe("https://socialtoken.com");
|
|
230
|
+
expect(response.Data?.telegramUrl).toBe("https://t.me/socialtoken");
|
|
231
|
+
expect(response.Data?.twitterUrl).toBe("https://twitter.com/socialtoken");
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should create sale with custom token image", async () => {
|
|
235
|
+
// Given
|
|
236
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1);
|
|
237
|
+
|
|
238
|
+
const createSaleDto = new CreateTokenSaleDTO(
|
|
239
|
+
"Image Token",
|
|
240
|
+
"IMG",
|
|
241
|
+
"A token with custom image",
|
|
242
|
+
"https://cdn.example.com/token-logo.png",
|
|
243
|
+
new BigNumber(0),
|
|
244
|
+
"ImageCollection",
|
|
245
|
+
"ImageCategory"
|
|
246
|
+
);
|
|
247
|
+
createSaleDto.websiteUrl = "https://example.com";
|
|
248
|
+
createSaleDto.uniqueKey = randomUniqueKey();
|
|
249
|
+
|
|
250
|
+
const signedDto = createSaleDto.signed(users.testUser1.privateKey);
|
|
251
|
+
|
|
252
|
+
// When
|
|
253
|
+
const response = await contract.CreateSale(ctx, signedDto);
|
|
254
|
+
|
|
255
|
+
// Then
|
|
256
|
+
expect(response.Status).toBe(1);
|
|
257
|
+
expect(response.Data?.image).toBe("https://cdn.example.com/token-logo.png");
|
|
258
|
+
});
|
|
259
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
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 {
|
|
16
|
+
TokenInstance,
|
|
17
|
+
TokenInstanceKey,
|
|
18
|
+
UserAlias,
|
|
19
|
+
asValidUserAlias,
|
|
20
|
+
randomUniqueKey
|
|
21
|
+
} from "@gala-chain/api";
|
|
22
|
+
import { fixture, users } from "@gala-chain/test";
|
|
23
|
+
import BigNumber from "bignumber.js";
|
|
24
|
+
|
|
25
|
+
import { FetchSaleDto, LaunchpadSale, ReverseBondingCurveConfigurationChainObject } from "../../api/types";
|
|
26
|
+
import { LaunchpadContract } from "../LaunchpadContract";
|
|
27
|
+
import launchpadgala from "../test/launchpadgala";
|
|
28
|
+
|
|
29
|
+
describe("fetchSaleDetails", () => {
|
|
30
|
+
let launchpadGalaInstance: TokenInstance;
|
|
31
|
+
let vaultAddress: UserAlias;
|
|
32
|
+
let sale: LaunchpadSale;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
launchpadGalaInstance = launchpadgala.tokenInstance();
|
|
36
|
+
vaultAddress = asValidUserAlias(`service|${launchpadgala.tokenClassKey().toStringKey()}$launchpad`);
|
|
37
|
+
|
|
38
|
+
// Initialize sale
|
|
39
|
+
sale = new LaunchpadSale(
|
|
40
|
+
vaultAddress,
|
|
41
|
+
launchpadGalaInstance.instanceKeyObj(),
|
|
42
|
+
undefined,
|
|
43
|
+
users.testUser1.identityKey
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should fetch existing sale details successfully", async () => {
|
|
48
|
+
// Given
|
|
49
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1).savedState(sale);
|
|
50
|
+
|
|
51
|
+
const fetchSaleDto = new FetchSaleDto(vaultAddress);
|
|
52
|
+
fetchSaleDto.uniqueKey = randomUniqueKey();
|
|
53
|
+
|
|
54
|
+
const signedDto = fetchSaleDto.signed(users.testUser1.privateKey);
|
|
55
|
+
|
|
56
|
+
// When
|
|
57
|
+
const response = await contract.FetchSaleDetails(ctx, signedDto);
|
|
58
|
+
|
|
59
|
+
// Then
|
|
60
|
+
expect(response.Status).toBe(1);
|
|
61
|
+
expect(response.Data?.vaultAddress).toBe(vaultAddress);
|
|
62
|
+
expect(response.Data?.saleOwner).toBe(users.testUser1.identityKey);
|
|
63
|
+
expect(response.Data?.sellingToken).toEqual(launchpadGalaInstance.instanceKeyObj());
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should handle sale with existing trades", async () => {
|
|
67
|
+
// Given
|
|
68
|
+
sale.buyToken(new BigNumber("100"), new BigNumber("0.01"));
|
|
69
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1).savedState(sale);
|
|
70
|
+
|
|
71
|
+
const fetchSaleDto = new FetchSaleDto(vaultAddress);
|
|
72
|
+
fetchSaleDto.uniqueKey = randomUniqueKey();
|
|
73
|
+
|
|
74
|
+
const signedDto = fetchSaleDto.signed(users.testUser1.privateKey);
|
|
75
|
+
|
|
76
|
+
// When
|
|
77
|
+
const response = await contract.FetchSaleDetails(ctx, signedDto);
|
|
78
|
+
|
|
79
|
+
// Then
|
|
80
|
+
expect(response.Status).toBe(1);
|
|
81
|
+
expect(response.Data?.fetchTokensSold()).toBe("100");
|
|
82
|
+
expect(new BigNumber(response.Data?.nativeTokenQuantity || "0").isPositive()).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should return sale with correct finalization status", async () => {
|
|
86
|
+
// Given - Create finalized sale
|
|
87
|
+
sale.finalizeSale();
|
|
88
|
+
const { ctx, contract } = fixture(LaunchpadContract).registeredUsers(users.testUser1).savedState(sale);
|
|
89
|
+
|
|
90
|
+
const fetchSaleDto = new FetchSaleDto(vaultAddress);
|
|
91
|
+
fetchSaleDto.uniqueKey = randomUniqueKey();
|
|
92
|
+
|
|
93
|
+
const signedDto = fetchSaleDto.signed(users.testUser1.privateKey);
|
|
94
|
+
|
|
95
|
+
// When
|
|
96
|
+
const response = await contract.FetchSaleDetails(ctx, signedDto);
|
|
97
|
+
|
|
98
|
+
// Then
|
|
99
|
+
expect(response.Status).toBe(1);
|
|
100
|
+
expect(response.Data?.saleStatus).toBe("Finished");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should fetch sale with reverse bonding curve configuration", async () => {
|
|
104
|
+
// Given - Create sale with reverse bonding curve
|
|
105
|
+
const tokenInstanceKey = new TokenInstanceKey();
|
|
106
|
+
tokenInstanceKey.collection = "TestCollection";
|
|
107
|
+
tokenInstanceKey.category = "TestCategory";
|
|
108
|
+
tokenInstanceKey.type = "TEST";
|
|
109
|
+
tokenInstanceKey.additionalKey = "test:key";
|
|
110
|
+
tokenInstanceKey.instance = new BigNumber(0);
|
|
111
|
+
|
|
112
|
+
const reverseBondingCurveConfig = new ReverseBondingCurveConfigurationChainObject(
|
|
113
|
+
new BigNumber(0.02), // minFeePortion
|
|
114
|
+
new BigNumber(0.05) // maxFeePortion
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const saleWithConfig = new LaunchpadSale(
|
|
118
|
+
vaultAddress,
|
|
119
|
+
tokenInstanceKey,
|
|
120
|
+
reverseBondingCurveConfig,
|
|
121
|
+
users.testUser1.identityKey
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
125
|
+
.registeredUsers(users.testUser1)
|
|
126
|
+
.savedState(saleWithConfig);
|
|
127
|
+
|
|
128
|
+
const fetchSaleDto = new FetchSaleDto(vaultAddress);
|
|
129
|
+
fetchSaleDto.uniqueKey = randomUniqueKey();
|
|
130
|
+
|
|
131
|
+
const signedDto = fetchSaleDto.signed(users.testUser1.privateKey);
|
|
132
|
+
|
|
133
|
+
// When
|
|
134
|
+
const response = await contract.FetchSaleDetails(ctx, signedDto);
|
|
135
|
+
|
|
136
|
+
// Then
|
|
137
|
+
expect(response.Status).toBe(1);
|
|
138
|
+
expect(response.Data?.reverseBondingCurveConfiguration).toBeDefined();
|
|
139
|
+
expect(response.Data?.reverseBondingCurveConfiguration?.maxFeePortion).toEqual(new BigNumber(0.05));
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -52,7 +52,7 @@ export async function finalizeSale(ctx: GalaChainContext, sale: LaunchpadSale):
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const platformFeePercentage = feeAllocation ? feeAllocation.platformFeePercentage : 0.01;
|
|
55
|
-
const ownerAllocationPercentage = feeAllocation ? feeAllocation.ownerAllocationPercentage : 0.
|
|
55
|
+
const ownerAllocationPercentage = feeAllocation ? feeAllocation.ownerAllocationPercentage : 0.05;
|
|
56
56
|
const liquidityAllocationPercentage = feeAllocation ? feeAllocation.liquidityAllocationPercentage : 0.94;
|
|
57
57
|
|
|
58
58
|
const nativeToken = sale.fetchNativeTokenInstanceKey();
|
|
@@ -0,0 +1,126 @@
|
|
|
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 { asValidUserAlias, randomUniqueKey } from "@gala-chain/api";
|
|
16
|
+
import { fixture, users } from "@gala-chain/test";
|
|
17
|
+
|
|
18
|
+
import { FinalizeTokenAllocationDto, LaunchpadFeeConfig } from "../../api/types";
|
|
19
|
+
import { LaunchpadContract } from "../LaunchpadContract";
|
|
20
|
+
|
|
21
|
+
describe("finalizeTokenAllocation", () => {
|
|
22
|
+
let feeConfig: LaunchpadFeeConfig;
|
|
23
|
+
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
feeConfig = new LaunchpadFeeConfig(asValidUserAlias("client|platformFeeAddress"), 0.01, [
|
|
26
|
+
users.admin.identityKey
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should create new token allocation successfully", async () => {
|
|
31
|
+
// Given
|
|
32
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
33
|
+
.caClientIdentity("test-admin", "CuratorOrg")
|
|
34
|
+
.registeredUsers(users.admin)
|
|
35
|
+
.savedState(feeConfig);
|
|
36
|
+
|
|
37
|
+
const finalizeDto = new FinalizeTokenAllocationDto();
|
|
38
|
+
finalizeDto.platformFeePercentage = 0.02;
|
|
39
|
+
finalizeDto.ownerFeePercentage = 0.03;
|
|
40
|
+
finalizeDto.uniqueKey = randomUniqueKey();
|
|
41
|
+
const signedDto = finalizeDto.signed(users.admin.privateKey);
|
|
42
|
+
|
|
43
|
+
// When
|
|
44
|
+
const response = await contract.FinalizeTokenAllocation(ctx, signedDto);
|
|
45
|
+
|
|
46
|
+
// Then
|
|
47
|
+
expect(response.Status).toBe(1);
|
|
48
|
+
expect(response.Data?.platformFeePercentage).toBe(0.02);
|
|
49
|
+
expect(response.Data?.ownerAllocationPercentage).toBe(0.03);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should update existing token allocation", async () => {
|
|
53
|
+
// Given - Create existing allocation first
|
|
54
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
55
|
+
.caClientIdentity("test-admin", "CuratorOrg")
|
|
56
|
+
.registeredUsers(users.admin)
|
|
57
|
+
.savedState(feeConfig);
|
|
58
|
+
|
|
59
|
+
const initialDto = new FinalizeTokenAllocationDto();
|
|
60
|
+
initialDto.platformFeePercentage = 0.01;
|
|
61
|
+
initialDto.ownerFeePercentage = 0.02;
|
|
62
|
+
initialDto.uniqueKey = randomUniqueKey();
|
|
63
|
+
const signedInitialDto = initialDto.signed(users.admin.privateKey);
|
|
64
|
+
|
|
65
|
+
await contract.FinalizeTokenAllocation(ctx, signedInitialDto);
|
|
66
|
+
|
|
67
|
+
// Update with new values
|
|
68
|
+
const updateDto = new FinalizeTokenAllocationDto();
|
|
69
|
+
updateDto.platformFeePercentage = 0.05;
|
|
70
|
+
updateDto.ownerFeePercentage = 0.06;
|
|
71
|
+
updateDto.uniqueKey = randomUniqueKey();
|
|
72
|
+
const signedUpdateDto = updateDto.signed(users.admin.privateKey);
|
|
73
|
+
|
|
74
|
+
// When
|
|
75
|
+
const response = await contract.FinalizeTokenAllocation(ctx, signedUpdateDto);
|
|
76
|
+
|
|
77
|
+
// Then
|
|
78
|
+
expect(response.Status).toBe(1);
|
|
79
|
+
expect(response.Data?.platformFeePercentage).toBe(0.05);
|
|
80
|
+
expect(response.Data?.ownerAllocationPercentage).toBe(0.06);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should handle zero percentage allocations", async () => {
|
|
84
|
+
// Given
|
|
85
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
86
|
+
.caClientIdentity("test-admin", "CuratorOrg")
|
|
87
|
+
.registeredUsers(users.admin)
|
|
88
|
+
.savedState(feeConfig);
|
|
89
|
+
|
|
90
|
+
const finalizeDto = new FinalizeTokenAllocationDto();
|
|
91
|
+
finalizeDto.platformFeePercentage = 0;
|
|
92
|
+
finalizeDto.ownerFeePercentage = 0;
|
|
93
|
+
finalizeDto.uniqueKey = randomUniqueKey();
|
|
94
|
+
const signedDto = finalizeDto.signed(users.admin.privateKey);
|
|
95
|
+
|
|
96
|
+
// When
|
|
97
|
+
const response = await contract.FinalizeTokenAllocation(ctx, signedDto);
|
|
98
|
+
|
|
99
|
+
// Then
|
|
100
|
+
expect(response.Status).toBe(1);
|
|
101
|
+
expect(response.Data?.platformFeePercentage).toBe(0);
|
|
102
|
+
expect(response.Data?.ownerAllocationPercentage).toBe(0);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should handle high percentage allocations", async () => {
|
|
106
|
+
// Given
|
|
107
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
108
|
+
.caClientIdentity("test-admin", "CuratorOrg")
|
|
109
|
+
.registeredUsers(users.admin)
|
|
110
|
+
.savedState(feeConfig);
|
|
111
|
+
|
|
112
|
+
const finalizeDto = new FinalizeTokenAllocationDto();
|
|
113
|
+
finalizeDto.platformFeePercentage = 0.1; // 10%
|
|
114
|
+
finalizeDto.ownerFeePercentage = 0.15; // 15%
|
|
115
|
+
finalizeDto.uniqueKey = randomUniqueKey();
|
|
116
|
+
const signedDto = finalizeDto.signed(users.admin.privateKey);
|
|
117
|
+
|
|
118
|
+
// When
|
|
119
|
+
const response = await contract.FinalizeTokenAllocation(ctx, signedDto);
|
|
120
|
+
|
|
121
|
+
// Then
|
|
122
|
+
expect(response.Status).toBe(1);
|
|
123
|
+
expect(response.Data?.platformFeePercentage).toBe(0.1);
|
|
124
|
+
expect(response.Data?.ownerAllocationPercentage).toBe(0.15);
|
|
125
|
+
});
|
|
126
|
+
});
|