@layerzerolabs/lz-v2-stellar-sdk 0.2.32 → 0.2.34
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/.turbo/turbo-test.log +373 -374
- package/dist/generated/oft.d.ts +3 -3
- package/dist/generated/oft.js +4 -4
- package/dist/generated/sac_manager.d.ts +26 -318
- package/dist/generated/sac_manager.js +23 -129
- package/package.json +10 -5
- package/src/generated/oft.ts +4 -4
- package/src/generated/sac_manager.ts +37 -320
- package/test/oft-sml.test.ts +72 -36
- package/test/sac-manager-redistribution.test.ts +38 -182
package/test/oft-sml.test.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { PacketSerializer, PacketV1Codec } from '@layerzerolabs/lz-v2-utilities'
|
|
|
17
17
|
import { Client as EndpointClient } from '../src/generated/endpoint';
|
|
18
18
|
import { Client as ExecutorHelperClient } from '../src/generated/executor_helper';
|
|
19
19
|
import { Client as OFTClient, SendParam } from '../src/generated/oft';
|
|
20
|
+
import { Client as SacManagerClient } from '../src/generated/sac_manager';
|
|
20
21
|
import { Client as SMLClient } from '../src/generated/sml';
|
|
21
22
|
import {
|
|
22
23
|
DEFAULT_DEPLOYER,
|
|
@@ -43,6 +44,7 @@ let chainB: ChainAddresses;
|
|
|
43
44
|
|
|
44
45
|
// OFT-specific addresses
|
|
45
46
|
let oftTokenAddress = '';
|
|
47
|
+
let sacManagerAddress = ''; // Mintable for Mint/Burn OFT (Chain B)
|
|
46
48
|
let lockUnlockOftAddress = ''; // Chain A
|
|
47
49
|
let mintBurnOftAddress = ''; // Chain B
|
|
48
50
|
|
|
@@ -87,6 +89,7 @@ describe('OFT Cross-Chain E2E Testing with SAC (SML)', async () => {
|
|
|
87
89
|
);
|
|
88
90
|
|
|
89
91
|
const OFT_WASM_PATH = path.join(wasmDir, 'oft.wasm');
|
|
92
|
+
const SAC_MANAGER_WASM_PATH = path.join(wasmDir, 'sac_manager.wasm');
|
|
90
93
|
|
|
91
94
|
beforeAll(async () => {
|
|
92
95
|
// Inject chain addresses from globalSetup
|
|
@@ -180,6 +183,53 @@ describe('OFT Cross-Chain E2E Testing with SAC (SML)', async () => {
|
|
|
180
183
|
console.log('✅ OFT Token SAC deployed:', oftTokenAddress);
|
|
181
184
|
});
|
|
182
185
|
|
|
186
|
+
it('Deploy SAC Manager and set SAC admin (mintable for Mint/Burn OFT)', async () => {
|
|
187
|
+
const sacManagerClient = await deployContract<SacManagerClient>(
|
|
188
|
+
SacManagerClient,
|
|
189
|
+
SAC_MANAGER_WASM_PATH,
|
|
190
|
+
{
|
|
191
|
+
sac_token: oftTokenAddress,
|
|
192
|
+
owner: DEFAULT_DEPLOYER.publicKey(),
|
|
193
|
+
},
|
|
194
|
+
DEFAULT_DEPLOYER,
|
|
195
|
+
);
|
|
196
|
+
sacManagerAddress = sacManagerClient.options.contractId;
|
|
197
|
+
console.log('✅ SAC Manager deployed:', sacManagerAddress);
|
|
198
|
+
|
|
199
|
+
const server = new rpc.Server(RPC_URL, { allowHttp: true });
|
|
200
|
+
const account = await server.getAccount(TOKEN_ISSUER.publicKey());
|
|
201
|
+
const setAdminTx = new TransactionBuilder(account, {
|
|
202
|
+
fee: BASE_FEE,
|
|
203
|
+
networkPassphrase: NETWORK_PASSPHRASE,
|
|
204
|
+
})
|
|
205
|
+
.addOperation(
|
|
206
|
+
Operation.invokeContractFunction({
|
|
207
|
+
contract: oftTokenAddress,
|
|
208
|
+
function: 'set_admin',
|
|
209
|
+
args: [Address.fromString(sacManagerAddress).toScVal()],
|
|
210
|
+
}),
|
|
211
|
+
)
|
|
212
|
+
.setTimeout(30)
|
|
213
|
+
.build();
|
|
214
|
+
|
|
215
|
+
const simulated = await server.simulateTransaction(setAdminTx);
|
|
216
|
+
if (rpc.Api.isSimulationError(simulated)) {
|
|
217
|
+
throw new Error(`Simulation failed: ${JSON.stringify(simulated)}`);
|
|
218
|
+
}
|
|
219
|
+
const preparedTx = rpc.assembleTransaction(setAdminTx, simulated).build();
|
|
220
|
+
preparedTx.sign(TOKEN_ISSUER);
|
|
221
|
+
|
|
222
|
+
const sendResult = await server.sendTransaction(preparedTx);
|
|
223
|
+
if (sendResult.status !== 'PENDING') {
|
|
224
|
+
throw new Error(`Failed to set admin: ${JSON.stringify(sendResult)}`);
|
|
225
|
+
}
|
|
226
|
+
const txResult = await server.pollTransaction(sendResult.hash);
|
|
227
|
+
if (txResult.status !== 'SUCCESS') {
|
|
228
|
+
throw new Error(`Failed to set admin: ${JSON.stringify(txResult)}`);
|
|
229
|
+
}
|
|
230
|
+
console.log('✅ SAC admin set to SAC Manager');
|
|
231
|
+
});
|
|
232
|
+
|
|
183
233
|
it('Deploy Lock/Unlock OFT on Chain A', async () => {
|
|
184
234
|
lockUnlockOftClient = await deployContract<OFTClient>(
|
|
185
235
|
OFTClient,
|
|
@@ -212,7 +262,7 @@ describe('OFT Cross-Chain E2E Testing with SAC (SML)', async () => {
|
|
|
212
262
|
endpoint: chainB.endpointV2, // Chain B endpoint
|
|
213
263
|
delegate: DEFAULT_DEPLOYER.publicKey(),
|
|
214
264
|
shared_decimals: SHARED_DECIMALS,
|
|
215
|
-
oft_type: { tag: 'MintBurn', values: [
|
|
265
|
+
oft_type: { tag: 'MintBurn', values: [sacManagerAddress] },
|
|
216
266
|
},
|
|
217
267
|
DEFAULT_DEPLOYER,
|
|
218
268
|
);
|
|
@@ -328,42 +378,28 @@ describe('OFT Cross-Chain E2E Testing with SAC (SML)', async () => {
|
|
|
328
378
|
console.log('✅ Mint/Burn OFT (Chain B) peer set to Lock/Unlock OFT for EID_A');
|
|
329
379
|
});
|
|
330
380
|
|
|
331
|
-
it('
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
381
|
+
it('Add Mint/Burn OFT as minter on SAC Manager (for receive/mint)', async () => {
|
|
382
|
+
const sacManagerClient = new SacManagerClient({
|
|
383
|
+
contractId: sacManagerAddress,
|
|
384
|
+
publicKey: DEFAULT_DEPLOYER.publicKey(),
|
|
385
|
+
signTransaction: async (tx: string) => {
|
|
386
|
+
const transaction = TransactionBuilder.fromXDR(tx, NETWORK_PASSPHRASE);
|
|
387
|
+
transaction.sign(DEFAULT_DEPLOYER);
|
|
388
|
+
return {
|
|
389
|
+
signedTxXdr: transaction.toXDR(),
|
|
390
|
+
signerAddress: DEFAULT_DEPLOYER.publicKey(),
|
|
391
|
+
};
|
|
392
|
+
},
|
|
393
|
+
rpcUrl: RPC_URL,
|
|
338
394
|
networkPassphrase: NETWORK_PASSPHRASE,
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
.setTimeout(30)
|
|
348
|
-
.build();
|
|
349
|
-
|
|
350
|
-
const simulated = await server.simulateTransaction(setAdminTx);
|
|
351
|
-
if (rpc.Api.isSimulationError(simulated)) {
|
|
352
|
-
throw new Error(`Simulation failed: ${JSON.stringify(simulated)}`);
|
|
353
|
-
}
|
|
354
|
-
const preparedTx = rpc.assembleTransaction(setAdminTx, simulated).build();
|
|
355
|
-
preparedTx.sign(TOKEN_ISSUER);
|
|
356
|
-
|
|
357
|
-
const sendResult = await server.sendTransaction(preparedTx);
|
|
358
|
-
if (sendResult.status !== 'PENDING') {
|
|
359
|
-
throw new Error(`Failed to set admin: ${JSON.stringify(sendResult)}`);
|
|
360
|
-
}
|
|
361
|
-
const txResult = await server.pollTransaction(sendResult.hash);
|
|
362
|
-
if (txResult.status !== 'SUCCESS') {
|
|
363
|
-
throw new Error(`Failed to set admin: ${JSON.stringify(txResult)}`);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
console.log('✅ SAC admin set to Mint/Burn OFT');
|
|
395
|
+
allowHttp: true,
|
|
396
|
+
});
|
|
397
|
+
const assembledTx = await sacManagerClient.set_minter({
|
|
398
|
+
minter: mintBurnOftAddress,
|
|
399
|
+
active: true,
|
|
400
|
+
});
|
|
401
|
+
await assembledTx.signAndSend();
|
|
402
|
+
console.log('✅ Mint/Burn OFT added as minter on SAC Manager');
|
|
367
403
|
});
|
|
368
404
|
});
|
|
369
405
|
|
|
@@ -26,7 +26,6 @@ import { getTokenAuthorized, getTokenBalance } from './utils';
|
|
|
26
26
|
// ============================================================================
|
|
27
27
|
|
|
28
28
|
const TOKEN_ISSUER = Keypair.random();
|
|
29
|
-
const REDISTRIBUTION_ADMIN = Keypair.random();
|
|
30
29
|
const USER_A = Keypair.random();
|
|
31
30
|
const USER_B = Keypair.random();
|
|
32
31
|
const USER_C = Keypair.random();
|
|
@@ -44,8 +43,7 @@ let sacManagerClient: SacManagerClient;
|
|
|
44
43
|
|
|
45
44
|
// Initial token amounts
|
|
46
45
|
const INITIAL_TOKEN_AMOUNT = '1000'; // 1000 tokens
|
|
47
|
-
const
|
|
48
|
-
const REDISTRIBUTE_AMOUNT = 50_0000000n; // 50 tokens (7 decimals)
|
|
46
|
+
const MINT_AMOUNT = 100_0000000n; // 100 tokens (7 decimals)
|
|
49
47
|
|
|
50
48
|
// ============================================================================
|
|
51
49
|
// Helper Functions
|
|
@@ -72,9 +70,6 @@ function createClientWithSigner(contractId: string, signer: Keypair): SacManager
|
|
|
72
70
|
});
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
// Note: The old executeRedistributeFundsWithAuth function has been removed
|
|
76
|
-
// because we now use the SacManagerClient directly which handles authorization properly
|
|
77
|
-
|
|
78
73
|
/**
|
|
79
74
|
* Invokes a SAC contract function using raw transaction building
|
|
80
75
|
*/
|
|
@@ -124,7 +119,7 @@ async function invokeSacFunction(
|
|
|
124
119
|
// Test Suite
|
|
125
120
|
// ============================================================================
|
|
126
121
|
|
|
127
|
-
describe('SAC Manager
|
|
122
|
+
describe('SAC Manager E2E Tests', async () => {
|
|
128
123
|
const repoRoot = await getFullyQualifiedRepoRootPath();
|
|
129
124
|
const wasmDir = path.join(
|
|
130
125
|
repoRoot,
|
|
@@ -140,25 +135,22 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
140
135
|
|
|
141
136
|
beforeAll(async () => {
|
|
142
137
|
console.log('\n====================================');
|
|
143
|
-
console.log('SAC Manager
|
|
138
|
+
console.log('SAC Manager E2E Tests');
|
|
144
139
|
console.log('====================================\n');
|
|
145
140
|
|
|
146
|
-
// Fund test accounts (including DEFAULT_DEPLOYER which is normally funded by globalSetup)
|
|
147
141
|
console.log('Funding test accounts...');
|
|
148
142
|
await fundAccount(DEFAULT_DEPLOYER.publicKey());
|
|
149
143
|
await fundAccount(TOKEN_ISSUER.publicKey());
|
|
150
|
-
await fundAccount(REDISTRIBUTION_ADMIN.publicKey());
|
|
151
144
|
await fundAccount(USER_A.publicKey());
|
|
152
145
|
await fundAccount(USER_B.publicKey());
|
|
153
146
|
await fundAccount(USER_C.publicKey());
|
|
154
147
|
console.log('Test accounts funded');
|
|
155
148
|
|
|
156
|
-
// Create the token asset
|
|
157
149
|
TOKEN_ASSET = new Asset(TOKEN_CODE, TOKEN_ISSUER.publicKey());
|
|
158
150
|
});
|
|
159
151
|
|
|
160
152
|
// ========================================================================
|
|
161
|
-
// Setup SAC Manager with SAC
|
|
153
|
+
// Setup SAC Manager with SAC
|
|
162
154
|
// ========================================================================
|
|
163
155
|
|
|
164
156
|
describe('Setup SAC Manager with SAC', () => {
|
|
@@ -166,9 +158,6 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
166
158
|
const server = new rpc.Server(RPC_URL, { allowHttp: true });
|
|
167
159
|
const issuerAccount = await server.getAccount(TOKEN_ISSUER.publicKey());
|
|
168
160
|
|
|
169
|
-
// Set AUTH_REVOCABLE and AUTH_CLAWBACK_ENABLED flags on issuer
|
|
170
|
-
// AUTH_REVOCABLE allows revoking authorization (blacklisting)
|
|
171
|
-
// AUTH_CLAWBACK_ENABLED allows clawback operations (required for redistribute_funds)
|
|
172
161
|
const authFlags = (AuthRevocableFlag | AuthClawbackEnabledFlag) as AuthFlag;
|
|
173
162
|
const setOptionsTx = new TransactionBuilder(issuerAccount, {
|
|
174
163
|
fee: BASE_FEE,
|
|
@@ -200,48 +189,35 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
200
189
|
it('Deploy SAC with trustlines and issue tokens', async () => {
|
|
201
190
|
const server = new rpc.Server(RPC_URL, { allowHttp: true });
|
|
202
191
|
|
|
203
|
-
// Create trustlines for all test accounts and issue tokens
|
|
204
192
|
const issuerAccount = await server.getAccount(TOKEN_ISSUER.publicKey());
|
|
205
193
|
const issueTx = new TransactionBuilder(issuerAccount, {
|
|
206
194
|
fee: BASE_FEE,
|
|
207
195
|
networkPassphrase: NETWORK_PASSPHRASE,
|
|
208
196
|
})
|
|
209
|
-
// Trustline for DEFAULT_DEPLOYER (will be the SAC manager admin)
|
|
210
197
|
.addOperation(
|
|
211
198
|
Operation.changeTrust({
|
|
212
199
|
asset: TOKEN_ASSET,
|
|
213
200
|
source: DEFAULT_DEPLOYER.publicKey(),
|
|
214
201
|
}),
|
|
215
202
|
)
|
|
216
|
-
// Trustline for REDISTRIBUTION_ADMIN
|
|
217
|
-
.addOperation(
|
|
218
|
-
Operation.changeTrust({
|
|
219
|
-
asset: TOKEN_ASSET,
|
|
220
|
-
source: REDISTRIBUTION_ADMIN.publicKey(),
|
|
221
|
-
}),
|
|
222
|
-
)
|
|
223
|
-
// Trustline for USER_A
|
|
224
203
|
.addOperation(
|
|
225
204
|
Operation.changeTrust({
|
|
226
205
|
asset: TOKEN_ASSET,
|
|
227
206
|
source: USER_A.publicKey(),
|
|
228
207
|
}),
|
|
229
208
|
)
|
|
230
|
-
// Trustline for USER_B
|
|
231
209
|
.addOperation(
|
|
232
210
|
Operation.changeTrust({
|
|
233
211
|
asset: TOKEN_ASSET,
|
|
234
212
|
source: USER_B.publicKey(),
|
|
235
213
|
}),
|
|
236
214
|
)
|
|
237
|
-
// Trustline for USER_C
|
|
238
215
|
.addOperation(
|
|
239
216
|
Operation.changeTrust({
|
|
240
217
|
asset: TOKEN_ASSET,
|
|
241
218
|
source: USER_C.publicKey(),
|
|
242
219
|
}),
|
|
243
220
|
)
|
|
244
|
-
// Issue tokens to USER_A (sender)
|
|
245
221
|
.addOperation(
|
|
246
222
|
Operation.payment({
|
|
247
223
|
asset: TOKEN_ASSET,
|
|
@@ -249,7 +225,6 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
249
225
|
destination: USER_A.publicKey(),
|
|
250
226
|
}),
|
|
251
227
|
)
|
|
252
|
-
// Issue tokens to USER_B (will be blacklisted)
|
|
253
228
|
.addOperation(
|
|
254
229
|
Operation.payment({
|
|
255
230
|
asset: TOKEN_ASSET,
|
|
@@ -260,14 +235,7 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
260
235
|
.setTimeout(30)
|
|
261
236
|
.build();
|
|
262
237
|
|
|
263
|
-
issueTx.sign(
|
|
264
|
-
TOKEN_ISSUER,
|
|
265
|
-
DEFAULT_DEPLOYER,
|
|
266
|
-
REDISTRIBUTION_ADMIN,
|
|
267
|
-
USER_A,
|
|
268
|
-
USER_B,
|
|
269
|
-
USER_C,
|
|
270
|
-
);
|
|
238
|
+
issueTx.sign(TOKEN_ISSUER, DEFAULT_DEPLOYER, USER_A, USER_B, USER_C);
|
|
271
239
|
|
|
272
240
|
const sendResult = await server.sendTransaction(issueTx);
|
|
273
241
|
if (sendResult.status !== 'PENDING') {
|
|
@@ -281,20 +249,17 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
281
249
|
|
|
282
250
|
console.log('Trustlines created and tokens issued');
|
|
283
251
|
|
|
284
|
-
// Deploy the SAC for the token
|
|
285
252
|
sacTokenAddress = await deployAssetSac(TOKEN_ASSET);
|
|
286
253
|
console.log('SAC deployed at:', sacTokenAddress);
|
|
287
254
|
});
|
|
288
255
|
|
|
289
|
-
it('Deploy SAC Manager contract
|
|
256
|
+
it('Deploy SAC Manager contract', async () => {
|
|
290
257
|
sacManagerClient = await deployContract<SacManagerClient>(
|
|
291
258
|
SacManagerClient,
|
|
292
259
|
SAC_MANAGER_WASM_PATH,
|
|
293
260
|
{
|
|
294
261
|
sac_token: sacTokenAddress,
|
|
295
262
|
owner: DEFAULT_DEPLOYER.publicKey(),
|
|
296
|
-
redistribution_enabled: true,
|
|
297
|
-
supply_control_enabled: false,
|
|
298
263
|
},
|
|
299
264
|
DEFAULT_DEPLOYER,
|
|
300
265
|
);
|
|
@@ -304,22 +269,25 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
304
269
|
});
|
|
305
270
|
|
|
306
271
|
it('Set SAC admin to SAC Manager', async () => {
|
|
307
|
-
// Set the SAC admin to the SAC manager contract
|
|
308
|
-
// This allows the SAC manager to call clawback, set_authorized, mint, etc.
|
|
309
272
|
await invokeSacFunction(
|
|
310
273
|
sacTokenAddress,
|
|
311
274
|
'set_admin',
|
|
312
275
|
[Address.fromString(sacManagerAddress).toScVal()],
|
|
313
276
|
TOKEN_ISSUER,
|
|
314
277
|
);
|
|
315
|
-
|
|
316
278
|
console.log('SAC admin set to SAC Manager');
|
|
317
279
|
});
|
|
318
280
|
|
|
319
|
-
it('
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
281
|
+
it('Add DEFAULT_DEPLOYER as minter', async () => {
|
|
282
|
+
const assembledTx = await sacManagerClient.set_minter({
|
|
283
|
+
minter: DEFAULT_DEPLOYER.publicKey(),
|
|
284
|
+
active: true,
|
|
285
|
+
});
|
|
286
|
+
await assembledTx.signAndSend();
|
|
287
|
+
const { result: minters } = await sacManagerClient.minters();
|
|
288
|
+
expect(minters).toBeDefined();
|
|
289
|
+
expect(minters?.length).toBeGreaterThanOrEqual(1);
|
|
290
|
+
console.log('DEFAULT_DEPLOYER added as minter');
|
|
323
291
|
});
|
|
324
292
|
|
|
325
293
|
it('Verify owner (DEFAULT_DEPLOYER) starts with zero balance', async () => {
|
|
@@ -337,8 +305,7 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
337
305
|
// ========================================================================
|
|
338
306
|
|
|
339
307
|
describe('Blacklist Management', () => {
|
|
340
|
-
it('Verify all accounts start authorized
|
|
341
|
-
// Check authorization status directly on the SAC
|
|
308
|
+
it('Verify all accounts start authorized', async () => {
|
|
342
309
|
const userAAuthorized = await getTokenAuthorized(USER_A.publicKey(), sacTokenAddress);
|
|
343
310
|
const userBAuthorized = await getTokenAuthorized(USER_B.publicKey(), sacTokenAddress);
|
|
344
311
|
const userCAuthorized = await getTokenAuthorized(USER_C.publicKey(), sacTokenAddress);
|
|
@@ -346,22 +313,19 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
346
313
|
expect(userAAuthorized).toBe(true);
|
|
347
314
|
expect(userBAuthorized).toBe(true);
|
|
348
315
|
expect(userCAuthorized).toBe(true);
|
|
349
|
-
|
|
350
316
|
console.log('All users start authorized');
|
|
351
317
|
});
|
|
352
318
|
|
|
353
319
|
it('Blacklist USER_B via set_authorized', async () => {
|
|
354
|
-
// Use DEFAULT_DEPLOYER (owner) to blacklist USER_B
|
|
355
320
|
const assembledTx = await sacManagerClient.set_authorized({
|
|
356
321
|
id: USER_B.publicKey(),
|
|
357
322
|
authorize: false,
|
|
358
323
|
});
|
|
359
|
-
|
|
360
324
|
await assembledTx.signAndSend();
|
|
361
325
|
console.log('USER_B blacklisted (authorized=false)');
|
|
362
326
|
});
|
|
363
327
|
|
|
364
|
-
it('Verify USER_B is blacklisted
|
|
328
|
+
it('Verify USER_B is blacklisted', async () => {
|
|
365
329
|
const authorized = await getTokenAuthorized(USER_B.publicKey(), sacTokenAddress);
|
|
366
330
|
expect(authorized).toBe(false);
|
|
367
331
|
console.log('USER_B authorized:', authorized);
|
|
@@ -369,54 +333,31 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
369
333
|
|
|
370
334
|
it('Non-admin cannot call set_authorized', async () => {
|
|
371
335
|
const userClient = createClientWithSigner(sacManagerAddress, USER_A);
|
|
372
|
-
|
|
373
336
|
const assembledTx = await userClient.set_authorized({
|
|
374
337
|
id: USER_C.publicKey(),
|
|
375
338
|
authorize: false,
|
|
376
339
|
});
|
|
377
|
-
|
|
378
340
|
await expect(assembledTx.signAndSend()).rejects.toThrow();
|
|
379
341
|
console.log('Non-admin correctly rejected from calling set_authorized');
|
|
380
342
|
});
|
|
381
343
|
|
|
382
344
|
it('Un-blacklist USER_B via set_authorized', async () => {
|
|
383
|
-
// Re-authorize USER_B
|
|
384
345
|
const assembledTx = await sacManagerClient.set_authorized({
|
|
385
346
|
id: USER_B.publicKey(),
|
|
386
347
|
authorize: true,
|
|
387
348
|
});
|
|
388
|
-
|
|
389
349
|
await assembledTx.signAndSend();
|
|
390
|
-
|
|
391
|
-
// Verify
|
|
392
350
|
const authorized = await getTokenAuthorized(USER_B.publicKey(), sacTokenAddress);
|
|
393
351
|
expect(authorized).toBe(true);
|
|
394
|
-
|
|
395
|
-
const isAuthorized = await getTokenAuthorized(USER_B.publicKey(), sacTokenAddress);
|
|
396
|
-
expect(isAuthorized).toBe(true);
|
|
397
|
-
|
|
398
352
|
console.log('USER_B un-blacklisted');
|
|
399
353
|
});
|
|
400
|
-
|
|
401
|
-
it('Re-blacklist USER_B for mint redirection tests', async () => {
|
|
402
|
-
const assembledTx = await sacManagerClient.set_authorized({
|
|
403
|
-
id: USER_B.publicKey(),
|
|
404
|
-
authorize: false,
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
await assembledTx.signAndSend();
|
|
408
|
-
|
|
409
|
-
const isAuthorized = await getTokenAuthorized(USER_B.publicKey(), sacTokenAddress);
|
|
410
|
-
expect(isAuthorized).toBe(false);
|
|
411
|
-
console.log('USER_B re-blacklisted for transfer tests');
|
|
412
|
-
});
|
|
413
354
|
});
|
|
414
355
|
|
|
415
356
|
// ========================================================================
|
|
416
|
-
// Mint
|
|
357
|
+
// Mint (Mintable interface – minter must be in minters list)
|
|
417
358
|
// ========================================================================
|
|
418
359
|
|
|
419
|
-
describe('Mint
|
|
360
|
+
describe('Mint', () => {
|
|
420
361
|
it('Verify initial balances', async () => {
|
|
421
362
|
const userABalance = await getTokenBalance(USER_A.publicKey(), sacTokenAddress);
|
|
422
363
|
const userBBalance = await getTokenBalance(USER_B.publicKey(), sacTokenAddress);
|
|
@@ -430,122 +371,38 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
430
371
|
console.log(` USER_A: ${userABalance}`);
|
|
431
372
|
console.log(` USER_B: ${userBBalance}`);
|
|
432
373
|
console.log(` USER_C: ${userCBalance}`);
|
|
433
|
-
console.log(` Owner
|
|
374
|
+
console.log(` Owner: ${ownerBalance}`);
|
|
434
375
|
|
|
435
|
-
expect(userABalance).toBe(10000000000n);
|
|
436
|
-
expect(userBBalance).toBe(10000000000n);
|
|
376
|
+
expect(userABalance).toBe(10000000000n);
|
|
377
|
+
expect(userBBalance).toBe(10000000000n);
|
|
437
378
|
expect(userCBalance).toBe(0n);
|
|
438
379
|
expect(ownerBalance).toBe(0n);
|
|
439
380
|
});
|
|
440
381
|
|
|
441
|
-
it('
|
|
382
|
+
it('Minter can mint to non-blacklisted address', async () => {
|
|
442
383
|
const userCBalanceBefore = await getTokenBalance(USER_C.publicKey(), sacTokenAddress);
|
|
443
384
|
|
|
444
|
-
const assembledTx = await sacManagerClient.
|
|
445
|
-
sender: DEFAULT_DEPLOYER.publicKey(),
|
|
385
|
+
const assembledTx = await sacManagerClient.mint({
|
|
446
386
|
to: USER_C.publicKey(),
|
|
447
|
-
amount:
|
|
387
|
+
amount: MINT_AMOUNT,
|
|
388
|
+
operation: DEFAULT_DEPLOYER.publicKey(),
|
|
448
389
|
});
|
|
449
390
|
await assembledTx.signAndSend();
|
|
450
391
|
|
|
451
|
-
// Verify balance increased
|
|
452
392
|
const userCBalance = await getTokenBalance(USER_C.publicKey(), sacTokenAddress);
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
console.log(` USER_C: ${userCBalance}`);
|
|
456
|
-
|
|
457
|
-
expect(userCBalance).toBe(userCBalanceBefore + TRANSFER_AMOUNT);
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
it('Admin mint to blacklisted address redirects to redistribution target (owner)', async () => {
|
|
461
|
-
const ownerBalanceBefore = await getTokenBalance(
|
|
462
|
-
DEFAULT_DEPLOYER.publicKey(),
|
|
463
|
-
sacTokenAddress,
|
|
464
|
-
);
|
|
465
|
-
const userBBalanceBefore = await getTokenBalance(USER_B.publicKey(), sacTokenAddress);
|
|
466
|
-
|
|
467
|
-
const assembledTx = await sacManagerClient.authorized_mint({
|
|
468
|
-
sender: DEFAULT_DEPLOYER.publicKey(),
|
|
469
|
-
to: USER_B.publicKey(), // Blacklisted!
|
|
470
|
-
amount: TRANSFER_AMOUNT,
|
|
471
|
-
});
|
|
472
|
-
await assembledTx.signAndSend();
|
|
473
|
-
|
|
474
|
-
// Verify balances - USER_B should not receive, owner should
|
|
475
|
-
const userBBalance = await getTokenBalance(USER_B.publicKey(), sacTokenAddress);
|
|
476
|
-
const ownerBalance = await getTokenBalance(
|
|
477
|
-
DEFAULT_DEPLOYER.publicKey(),
|
|
478
|
-
sacTokenAddress,
|
|
479
|
-
);
|
|
480
|
-
|
|
481
|
-
console.log('\nAfter authorized_mint to blacklisted (USER_B):');
|
|
482
|
-
console.log(` USER_B: ${userBBalance} (unchanged)`);
|
|
483
|
-
console.log(` Owner (received redirected): ${ownerBalance}`);
|
|
484
|
-
|
|
485
|
-
// USER_B balance should be unchanged
|
|
486
|
-
expect(userBBalance).toBe(userBBalanceBefore);
|
|
487
|
-
// Owner should receive the redirected tokens
|
|
488
|
-
expect(ownerBalance).toBe(ownerBalanceBefore + TRANSFER_AMOUNT);
|
|
489
|
-
});
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
// ========================================================================
|
|
493
|
-
// Redistribute Funds
|
|
494
|
-
// ========================================================================
|
|
495
|
-
|
|
496
|
-
describe('Redistribute Funds', () => {
|
|
497
|
-
it('Redistribute funds from blacklisted account', async () => {
|
|
498
|
-
const ownerBalanceBefore = await getTokenBalance(
|
|
499
|
-
DEFAULT_DEPLOYER.publicKey(),
|
|
500
|
-
sacTokenAddress,
|
|
501
|
-
);
|
|
502
|
-
const userBBalanceBefore = await getTokenBalance(USER_B.publicKey(), sacTokenAddress);
|
|
503
|
-
|
|
504
|
-
console.log('\nBefore redistribute_blacklisted_funds:');
|
|
505
|
-
console.log(` USER_B: ${userBBalanceBefore}`);
|
|
506
|
-
console.log(` Owner: ${ownerBalanceBefore}`);
|
|
507
|
-
|
|
508
|
-
// Only owner can redistribute - use DEFAULT_DEPLOYER
|
|
509
|
-
const assembledTx = await sacManagerClient.redistribute_blacklisted_funds({
|
|
510
|
-
from: USER_B.publicKey(),
|
|
511
|
-
amount: REDISTRIBUTE_AMOUNT,
|
|
512
|
-
});
|
|
513
|
-
await assembledTx.signAndSend();
|
|
514
|
-
|
|
515
|
-
// Verify balances
|
|
516
|
-
const userBBalance = await getTokenBalance(USER_B.publicKey(), sacTokenAddress);
|
|
517
|
-
const ownerBalance = await getTokenBalance(
|
|
518
|
-
DEFAULT_DEPLOYER.publicKey(),
|
|
519
|
-
sacTokenAddress,
|
|
520
|
-
);
|
|
521
|
-
|
|
522
|
-
console.log('\nAfter redistribute_blacklisted_funds:');
|
|
523
|
-
console.log(` USER_B: ${userBBalance}`);
|
|
524
|
-
console.log(` Owner: ${ownerBalance}`);
|
|
525
|
-
|
|
526
|
-
expect(userBBalance).toBe(userBBalanceBefore - REDISTRIBUTE_AMOUNT);
|
|
527
|
-
expect(ownerBalance).toBe(ownerBalanceBefore + REDISTRIBUTE_AMOUNT);
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
it('Cannot redistribute from non-blacklisted account', async () => {
|
|
531
|
-
// USER_A is not blacklisted - this should fail even for owner
|
|
532
|
-
const assembledTx = await sacManagerClient.redistribute_blacklisted_funds({
|
|
533
|
-
from: USER_A.publicKey(),
|
|
534
|
-
amount: REDISTRIBUTE_AMOUNT,
|
|
535
|
-
});
|
|
536
|
-
await expect(assembledTx.signAndSend()).rejects.toThrow();
|
|
537
|
-
console.log('Correctly rejected redistribution from non-blacklisted account');
|
|
393
|
+
console.log('\nAfter mint to USER_C:', userCBalance);
|
|
394
|
+
expect(userCBalance).toBe(userCBalanceBefore + MINT_AMOUNT);
|
|
538
395
|
});
|
|
539
396
|
|
|
540
|
-
it('Non-
|
|
541
|
-
// USER_A is not the owner - this should fail
|
|
397
|
+
it('Non-minter cannot mint', async () => {
|
|
542
398
|
const userClient = createClientWithSigner(sacManagerAddress, USER_A);
|
|
543
|
-
const assembledTx = await userClient.
|
|
544
|
-
|
|
545
|
-
amount:
|
|
399
|
+
const assembledTx = await userClient.mint({
|
|
400
|
+
to: USER_C.publicKey(),
|
|
401
|
+
amount: MINT_AMOUNT,
|
|
402
|
+
operation: USER_A.publicKey(),
|
|
546
403
|
});
|
|
547
404
|
await expect(assembledTx.signAndSend()).rejects.toThrow();
|
|
548
|
-
console.log('Non-
|
|
405
|
+
console.log('Non-minter correctly rejected');
|
|
549
406
|
});
|
|
550
407
|
});
|
|
551
408
|
|
|
@@ -567,12 +424,11 @@ describe('SAC Manager Redistribution E2E Tests', async () => {
|
|
|
567
424
|
console.log('Final Balance Summary');
|
|
568
425
|
console.log('========================================');
|
|
569
426
|
console.log(` USER_A: ${userABalance}`);
|
|
570
|
-
console.log(` USER_B
|
|
427
|
+
console.log(` USER_B: ${userBBalance}`);
|
|
571
428
|
console.log(` USER_C: ${userCBalance}`);
|
|
572
|
-
console.log(` Owner
|
|
429
|
+
console.log(` Owner: ${ownerBalance}`);
|
|
573
430
|
console.log('========================================\n');
|
|
574
|
-
|
|
575
|
-
console.log('SAC Manager Redistribution E2E tests completed successfully!');
|
|
431
|
+
console.log('SAC Manager E2E tests completed successfully!');
|
|
576
432
|
});
|
|
577
433
|
});
|
|
578
434
|
});
|