/** * E2E 测试: 自动创建账号 (MPC 2-of-3) * * 测试流程: * 1. 调用 POST /user/auto-create 创建账号 * 2. 验证返回的账号信息 * 3. 验证钱包地址格式 * 4. 验证 MPC 分片数据 */ import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import * as request from 'supertest'; import { AppModule } from '../src/app.module'; describe('AutoCreateAccount (e2e)', () => { let app: INestApplication; beforeAll(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); app.useGlobalPipes(new ValidationPipe({ transform: true })); await app.init(); }); afterAll(async () => { await app.close(); }); describe('POST /user/auto-create', () => { it('should create account with MPC 2-of-3 wallet', async () => { const deviceId = `test-device-${Date.now()}`; const response = await request(app.getHttpServer()) .post('/user/auto-create') .send({ deviceId, deviceName: 'Test Device', }) .expect(201); const body = response.body; // 验证基本字段 expect(body).toHaveProperty('userId'); expect(body).toHaveProperty('accountSequence'); expect(body).toHaveProperty('referralCode'); expect(body).toHaveProperty('accessToken'); expect(body).toHaveProperty('refreshToken'); expect(body).toHaveProperty('walletAddresses'); // 验证钱包地址格式 // BSC 和 KAVA 是 EVM 兼容链,使用 0x 前缀的地址 expect(body.walletAddresses.bsc).toMatch(/^0x[a-fA-F0-9]{40}$/); expect(body.walletAddresses.kava).toMatch(/^0x[a-fA-F0-9]{40}$/); // DST 是 Cosmos 链,使用 Bech32 格式 (dst1...) expect(body.walletAddresses.dst).toMatch(/^dst1[a-z0-9]{38,58}$/); // BSC 和 KAVA 地址应该相同 (同一个 MPC 公钥派生的 EVM 地址) expect(body.walletAddresses.bsc).toBe(body.walletAddresses.kava); // DST 地址是不同格式,不应该与 EVM 地址相同 expect(body.walletAddresses.dst).not.toBe(body.walletAddresses.bsc); // 验证 MPC 相关字段 expect(body).toHaveProperty('clientShareData'); expect(body).toHaveProperty('publicKey'); expect(body.clientShareData).toBeTruthy(); expect(body.publicKey).toBeTruthy(); // MPC 模式下 mnemonic 应该为空 expect(body.mnemonic).toBe(''); // 验证账号序列号是正整数 expect(typeof body.accountSequence).toBe('number'); expect(body.accountSequence).toBeGreaterThan(0); // 验证推荐码格式 (假设是 6-10 位字母数字) expect(body.referralCode).toMatch(/^[A-Z0-9]{6,10}$/); console.log('Created account:', { userId: body.userId, accountSequence: body.accountSequence, referralCode: body.referralCode, publicKey: body.publicKey?.substring(0, 20) + '...', bscAddress: body.walletAddresses.bsc, }); }); it('should create different accounts for different devices', async () => { const deviceId1 = `test-device-a-${Date.now()}`; const deviceId2 = `test-device-b-${Date.now()}`; const [response1, response2] = await Promise.all([ request(app.getHttpServer()) .post('/user/auto-create') .send({ deviceId: deviceId1 }), request(app.getHttpServer()) .post('/user/auto-create') .send({ deviceId: deviceId2 }), ]); // 两个账号应该有不同的序列号和钱包地址 expect(response1.body.accountSequence).not.toBe(response2.body.accountSequence); expect(response1.body.walletAddresses.bsc).not.toBe(response2.body.walletAddresses.bsc); expect(response1.body.publicKey).not.toBe(response2.body.publicKey); }); it('should reject invalid device id', async () => { await request(app.getHttpServer()) .post('/user/auto-create') .send({ deviceId: '', // 空设备ID }) .expect(400); }); it('should handle inviter referral code', async () => { // 先创建一个账号作为邀请人 const inviterResponse = await request(app.getHttpServer()) .post('/user/auto-create') .send({ deviceId: `inviter-${Date.now()}` }) .expect(201); const inviterReferralCode = inviterResponse.body.referralCode; // 使用邀请码创建新账号 const inviteeResponse = await request(app.getHttpServer()) .post('/user/auto-create') .send({ deviceId: `invitee-${Date.now()}`, inviterReferralCode, }) .expect(201); expect(inviteeResponse.body.accountSequence).toBeGreaterThan( inviterResponse.body.accountSequence, ); }); }); });