rwadurian/backend/services/identity-service/test/auto-create-account.e2e-spe...

144 lines
4.8 KiB
TypeScript

/**
* 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,
);
});
});
});