@gala-chain/launchpad 1.0.9 → 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/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/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 +90 -20
- 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/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,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
|
+
});
|
|
@@ -0,0 +1,284 @@
|
|
|
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
|
+
TokenBalance,
|
|
17
|
+
TokenClass,
|
|
18
|
+
TokenClassKey,
|
|
19
|
+
TokenInstance,
|
|
20
|
+
UserAlias,
|
|
21
|
+
asValidUserAlias,
|
|
22
|
+
randomUniqueKey
|
|
23
|
+
} from "@gala-chain/api";
|
|
24
|
+
import { InvalidDecimalError } from "@gala-chain/chaincode";
|
|
25
|
+
import { currency, fixture, transactionError, users } from "@gala-chain/test";
|
|
26
|
+
import BigNumber from "bignumber.js";
|
|
27
|
+
import { plainToInstance } from "class-transformer";
|
|
28
|
+
|
|
29
|
+
import { ExactTokenQuantityDto, LaunchpadSale } from "../../api/types";
|
|
30
|
+
import { LaunchpadContract } from "../LaunchpadContract";
|
|
31
|
+
import launchpadgala from "../test/launchpadgala";
|
|
32
|
+
|
|
33
|
+
describe("sellExactToken", () => {
|
|
34
|
+
let currencyClass: TokenClass;
|
|
35
|
+
let currencyInstance: TokenInstance;
|
|
36
|
+
let launchpadGalaClass: TokenClass;
|
|
37
|
+
let launchpadGalaInstance: TokenInstance;
|
|
38
|
+
let launchpadGalaClassKey: TokenClassKey;
|
|
39
|
+
let vaultAddress: UserAlias;
|
|
40
|
+
let sale: LaunchpadSale;
|
|
41
|
+
let salelaunchpadGalaBalance: TokenBalance;
|
|
42
|
+
let saleCurrencyBalance: TokenBalance;
|
|
43
|
+
let userlaunchpadGalaBalance: TokenBalance;
|
|
44
|
+
let userCurrencyBalance: TokenBalance;
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
currencyClass = currency.tokenClass();
|
|
48
|
+
currencyInstance = currency.tokenInstance();
|
|
49
|
+
launchpadGalaClass = launchpadgala.tokenClass();
|
|
50
|
+
launchpadGalaInstance = launchpadgala.tokenInstance();
|
|
51
|
+
launchpadGalaClassKey = launchpadgala.tokenClassKey();
|
|
52
|
+
|
|
53
|
+
vaultAddress = asValidUserAlias(`service|${launchpadGalaClassKey.toStringKey()}$launchpad`);
|
|
54
|
+
|
|
55
|
+
// Initialize sale with manual values
|
|
56
|
+
sale = new LaunchpadSale(
|
|
57
|
+
vaultAddress,
|
|
58
|
+
currencyInstance.instanceKeyObj(),
|
|
59
|
+
undefined,
|
|
60
|
+
users.testUser1.identityKey
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
// Create sale balances - sale needs tokens to pay out
|
|
64
|
+
salelaunchpadGalaBalance = plainToInstance(TokenBalance, {
|
|
65
|
+
...launchpadgala.tokenBalance(),
|
|
66
|
+
owner: vaultAddress,
|
|
67
|
+
quantity: new BigNumber("1000000") // Large amount in vault
|
|
68
|
+
});
|
|
69
|
+
saleCurrencyBalance = plainToInstance(TokenBalance, {
|
|
70
|
+
...currency.tokenBalance(),
|
|
71
|
+
owner: vaultAddress,
|
|
72
|
+
quantity: new BigNumber("1000000") // Large amount in vault
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Create user balances - user needs tokens to sell
|
|
76
|
+
userlaunchpadGalaBalance = plainToInstance(TokenBalance, {
|
|
77
|
+
...launchpadgala.tokenBalance(),
|
|
78
|
+
owner: users.testUser1.identityKey,
|
|
79
|
+
quantity: new BigNumber("10000") // User has tokens to sell
|
|
80
|
+
});
|
|
81
|
+
userCurrencyBalance = plainToInstance(TokenBalance, {
|
|
82
|
+
...currency.tokenBalance(),
|
|
83
|
+
owner: users.testUser1.identityKey,
|
|
84
|
+
quantity: new BigNumber("1000") // User has some CURRENCY tokens
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should sell exact token amount successfully", async () => {
|
|
89
|
+
// Given
|
|
90
|
+
sale.buyToken(new BigNumber("1000"), new BigNumber("50")); // Users bought tokens, sale now has GALA
|
|
91
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
92
|
+
.registeredUsers(users.testUser1)
|
|
93
|
+
.savedState(
|
|
94
|
+
currencyClass,
|
|
95
|
+
currencyInstance,
|
|
96
|
+
launchpadGalaClass,
|
|
97
|
+
launchpadGalaInstance,
|
|
98
|
+
sale,
|
|
99
|
+
salelaunchpadGalaBalance,
|
|
100
|
+
saleCurrencyBalance,
|
|
101
|
+
userlaunchpadGalaBalance,
|
|
102
|
+
userCurrencyBalance
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const sellDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("100"));
|
|
106
|
+
sellDto.uniqueKey = randomUniqueKey();
|
|
107
|
+
const signedDto = sellDto.signed(users.testUser1.privateKey);
|
|
108
|
+
|
|
109
|
+
// When
|
|
110
|
+
const response = await contract.SellExactToken(ctx, signedDto);
|
|
111
|
+
|
|
112
|
+
// Then
|
|
113
|
+
expect(response.Status).toBe(1);
|
|
114
|
+
expect(response.Data).toHaveProperty("outputQuantity");
|
|
115
|
+
expect(response.Data).toHaveProperty("inputQuantity", "100");
|
|
116
|
+
expect(response.Data).toHaveProperty("isFinalized");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should reject sell when native token has 0 decimals and bonding curve produces fractional quantity", async () => {
|
|
120
|
+
// Given
|
|
121
|
+
const zeroDecimalNativeClass = plainToInstance(TokenClass, {
|
|
122
|
+
...launchpadgala.tokenClassPlain(),
|
|
123
|
+
decimals: 0 // Integer-only native token
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Simulate prior buys to establish sale state
|
|
127
|
+
sale.buyToken(new BigNumber("5000"), new BigNumber("100"));
|
|
128
|
+
|
|
129
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
130
|
+
.registeredUsers(users.testUser1)
|
|
131
|
+
.savedState(
|
|
132
|
+
currencyClass,
|
|
133
|
+
currencyInstance,
|
|
134
|
+
zeroDecimalNativeClass,
|
|
135
|
+
launchpadGalaInstance,
|
|
136
|
+
sale,
|
|
137
|
+
salelaunchpadGalaBalance,
|
|
138
|
+
saleCurrencyBalance,
|
|
139
|
+
userlaunchpadGalaBalance,
|
|
140
|
+
userCurrencyBalance
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Choose a token quantity that will produce fractional native tokens from bonding curve
|
|
144
|
+
const sellDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("100"));
|
|
145
|
+
sellDto.uniqueKey = randomUniqueKey();
|
|
146
|
+
const signedDto = sellDto.signed(users.testUser1.privateKey);
|
|
147
|
+
|
|
148
|
+
// When
|
|
149
|
+
const response = await contract.SellExactToken(ctx, signedDto);
|
|
150
|
+
|
|
151
|
+
// Then - Expect error due to decimal precision mismatch
|
|
152
|
+
expect(response).toEqual(
|
|
153
|
+
transactionError(new InvalidDecimalError(new BigNumber("0.00166022"), zeroDecimalNativeClass.decimals))
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("should reject sell when meme token has 0 decimals and input dto contains greater fractional precision", async () => {
|
|
158
|
+
// Given
|
|
159
|
+
const zeroDecimalMemeClass = plainToInstance(TokenClass, {
|
|
160
|
+
...currency.tokenClassPlain(),
|
|
161
|
+
decimals: 0 // Integer-only native token
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Simulate prior buys to establish sale state
|
|
165
|
+
sale.buyToken(new BigNumber("5000"), new BigNumber("100"));
|
|
166
|
+
|
|
167
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
168
|
+
.registeredUsers(users.testUser1)
|
|
169
|
+
.savedState(
|
|
170
|
+
zeroDecimalMemeClass,
|
|
171
|
+
currencyInstance,
|
|
172
|
+
launchpadGalaClass,
|
|
173
|
+
launchpadGalaInstance,
|
|
174
|
+
sale,
|
|
175
|
+
salelaunchpadGalaBalance,
|
|
176
|
+
saleCurrencyBalance,
|
|
177
|
+
userlaunchpadGalaBalance,
|
|
178
|
+
userCurrencyBalance
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// Choose a token quantity that will produce fractional native tokens from bonding curve
|
|
182
|
+
const sellDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("100.555"));
|
|
183
|
+
sellDto.uniqueKey = randomUniqueKey();
|
|
184
|
+
const signedDto = sellDto.signed(users.testUser1.privateKey);
|
|
185
|
+
|
|
186
|
+
// When
|
|
187
|
+
const response = await contract.SellExactToken(ctx, signedDto);
|
|
188
|
+
|
|
189
|
+
// Then - Expect error due to decimal precision mismatch
|
|
190
|
+
expect(response).toEqual(
|
|
191
|
+
transactionError(new InvalidDecimalError(sellDto.tokenQuantity, zeroDecimalMemeClass.decimals))
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("should handle small token sell amount", async () => {
|
|
196
|
+
// Given
|
|
197
|
+
sale.buyToken(new BigNumber("500"), new BigNumber("25")); // Users bought tokens, sale now has GALA
|
|
198
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
199
|
+
.registeredUsers(users.testUser1)
|
|
200
|
+
.savedState(
|
|
201
|
+
currencyClass,
|
|
202
|
+
currencyInstance,
|
|
203
|
+
launchpadGalaClass,
|
|
204
|
+
launchpadGalaInstance,
|
|
205
|
+
sale,
|
|
206
|
+
salelaunchpadGalaBalance,
|
|
207
|
+
saleCurrencyBalance,
|
|
208
|
+
userlaunchpadGalaBalance,
|
|
209
|
+
userCurrencyBalance
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const sellDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("1"));
|
|
213
|
+
sellDto.uniqueKey = randomUniqueKey();
|
|
214
|
+
const signedDto = sellDto.signed(users.testUser1.privateKey);
|
|
215
|
+
|
|
216
|
+
// When
|
|
217
|
+
const response = await contract.SellExactToken(ctx, signedDto);
|
|
218
|
+
|
|
219
|
+
// Then
|
|
220
|
+
expect(response.Status).toBe(1);
|
|
221
|
+
expect(response.Data?.inputQuantity).toBe("1");
|
|
222
|
+
expect(new BigNumber(response.Data?.outputQuantity || "0").isPositive()).toBe(true);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("should handle sell with expected native token parameter", async () => {
|
|
226
|
+
// Given
|
|
227
|
+
sale.buyToken(new BigNumber("800"), new BigNumber("40")); // Users bought tokens, sale now has GALA
|
|
228
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
229
|
+
.registeredUsers(users.testUser1)
|
|
230
|
+
.savedState(
|
|
231
|
+
currencyClass,
|
|
232
|
+
currencyInstance,
|
|
233
|
+
launchpadGalaClass,
|
|
234
|
+
launchpadGalaInstance,
|
|
235
|
+
sale,
|
|
236
|
+
salelaunchpadGalaBalance,
|
|
237
|
+
saleCurrencyBalance,
|
|
238
|
+
userlaunchpadGalaBalance,
|
|
239
|
+
userCurrencyBalance
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const sellDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("50"));
|
|
243
|
+
sellDto.expectedNativeToken = new BigNumber("0.0001"); // Set realistic expectation for slippage protection
|
|
244
|
+
sellDto.uniqueKey = randomUniqueKey();
|
|
245
|
+
const signedDto = sellDto.signed(users.testUser1.privateKey);
|
|
246
|
+
|
|
247
|
+
// When
|
|
248
|
+
const response = await contract.SellExactToken(ctx, signedDto);
|
|
249
|
+
|
|
250
|
+
// Then
|
|
251
|
+
expect(response.Status).toBe(1);
|
|
252
|
+
expect(response.Data?.inputQuantity).toBe("50");
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("should handle large token sell amount", async () => {
|
|
256
|
+
// Given
|
|
257
|
+
sale.buyToken(new BigNumber("2000"), new BigNumber("100")); // Users bought tokens, sale now has GALA
|
|
258
|
+
const { ctx, contract } = fixture(LaunchpadContract)
|
|
259
|
+
.registeredUsers(users.testUser1)
|
|
260
|
+
.savedState(
|
|
261
|
+
currencyClass,
|
|
262
|
+
currencyInstance,
|
|
263
|
+
launchpadGalaClass,
|
|
264
|
+
launchpadGalaInstance,
|
|
265
|
+
sale,
|
|
266
|
+
salelaunchpadGalaBalance,
|
|
267
|
+
saleCurrencyBalance,
|
|
268
|
+
userlaunchpadGalaBalance,
|
|
269
|
+
userCurrencyBalance
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
const sellDto = new ExactTokenQuantityDto(vaultAddress, new BigNumber("500"));
|
|
273
|
+
sellDto.uniqueKey = randomUniqueKey();
|
|
274
|
+
const signedDto = sellDto.signed(users.testUser1.privateKey);
|
|
275
|
+
|
|
276
|
+
// When
|
|
277
|
+
const response = await contract.SellExactToken(ctx, signedDto);
|
|
278
|
+
|
|
279
|
+
// Then
|
|
280
|
+
expect(response.Status).toBe(1);
|
|
281
|
+
expect(response.Data?.inputQuantity).toBe("500");
|
|
282
|
+
expect(new BigNumber(response.Data?.outputQuantity || "0").isPositive()).toBe(true);
|
|
283
|
+
});
|
|
284
|
+
});
|