@novasamatech/host-chat 0.8.12 → 0.9.1
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/dist/codec/attachment.d.ts +1 -1
- package/dist/codec/attachment.js +2 -2
- package/dist/codec/contact.js +2 -1
- package/dist/codec/localMessage.d.ts +1 -1
- package/dist/codec/localMessage.js +2 -2
- package/dist/codec/message.d.ts +5 -5
- package/dist/codec/message.js +7 -4
- package/dist/codec/message.spec.js +12 -94
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const MediaThumbnail: import("scale
|
|
1
|
+
export declare const MediaThumbnail: import("@novasamatech/scale").BytesCodec<undefined>;
|
|
2
2
|
export declare const GeneralFileMeta: import("scale-ts").Codec<{
|
|
3
3
|
mimeType: string;
|
|
4
4
|
fileSize: number;
|
package/dist/codec/attachment.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Enum } from '@novasamatech/scale';
|
|
2
|
-
import {
|
|
1
|
+
import { Bytes, Enum } from '@novasamatech/scale';
|
|
2
|
+
import { Option, Struct, str, u32 } from 'scale-ts';
|
|
3
3
|
// UTF-8 bytes of a Wolt-spec blurhash string (componentX=4, componentY=3).
|
|
4
4
|
// Wire type is Vec<u8>; the bytes themselves are the ASCII blurhash.
|
|
5
5
|
export const MediaThumbnail = Bytes();
|
package/dist/codec/contact.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { Bytes } from '@novasamatech/scale';
|
|
1
2
|
import { AccountIdCodec } from '@novasamatech/statement-store';
|
|
2
|
-
import {
|
|
3
|
+
import { Option, Struct, str } from 'scale-ts';
|
|
3
4
|
export const Contact = Struct({
|
|
4
5
|
username: str,
|
|
5
6
|
accountId: AccountIdCodec,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Enum, Status } from '@novasamatech/scale';
|
|
1
|
+
import { Bytes, Enum, Status } from '@novasamatech/scale';
|
|
2
2
|
import { AccountIdCodec } from '@novasamatech/statement-store';
|
|
3
|
-
import {
|
|
3
|
+
import { Struct, u64 } from 'scale-ts';
|
|
4
4
|
import { ChatMessage } from './message.js';
|
|
5
5
|
export const OutgoingStatus = Status('new', 'sent', 'delivered');
|
|
6
6
|
export const IncomingStatus = Status('new', 'seen');
|
package/dist/codec/message.d.ts
CHANGED
|
@@ -43,10 +43,10 @@ export declare const RichTextContent: import("scale-ts").Codec<{
|
|
|
43
43
|
};
|
|
44
44
|
}[] | undefined;
|
|
45
45
|
}>;
|
|
46
|
-
export declare const Platform: import("scale-ts").Codec<"Android" | "iOS">;
|
|
46
|
+
export declare const Platform: import("scale-ts").Codec<"Android" | "iOS" | "iOSVoIP">;
|
|
47
47
|
export declare const TokenContent: import("scale-ts").Codec<{
|
|
48
48
|
token: `0x${string}`;
|
|
49
|
-
platform: "Android" | "iOS";
|
|
49
|
+
platform: "Android" | "iOS" | "iOSVoIP";
|
|
50
50
|
}>;
|
|
51
51
|
export declare const SendContent: import("scale-ts").Codec<{
|
|
52
52
|
amount: number | bigint;
|
|
@@ -200,7 +200,7 @@ export declare const MessageContent: import("scale-ts").Codec<{
|
|
|
200
200
|
tag: "token";
|
|
201
201
|
value: {
|
|
202
202
|
token: `0x${string}`;
|
|
203
|
-
platform: "Android" | "iOS";
|
|
203
|
+
platform: "Android" | "iOS" | "iOSVoIP";
|
|
204
204
|
};
|
|
205
205
|
} | {
|
|
206
206
|
tag: "send";
|
|
@@ -442,7 +442,7 @@ export declare const VersionedMessageContent: import("scale-ts").Codec<{
|
|
|
442
442
|
tag: "token";
|
|
443
443
|
value: {
|
|
444
444
|
token: `0x${string}`;
|
|
445
|
-
platform: "Android" | "iOS";
|
|
445
|
+
platform: "Android" | "iOS" | "iOSVoIP";
|
|
446
446
|
};
|
|
447
447
|
} | {
|
|
448
448
|
tag: "send";
|
|
@@ -688,7 +688,7 @@ export declare const ChatMessage: import("scale-ts").Codec<{
|
|
|
688
688
|
tag: "token";
|
|
689
689
|
value: {
|
|
690
690
|
token: `0x${string}`;
|
|
691
|
-
platform: "Android" | "iOS";
|
|
691
|
+
platform: "Android" | "iOS" | "iOSVoIP";
|
|
692
692
|
};
|
|
693
693
|
} | {
|
|
694
694
|
tag: "send";
|
package/dist/codec/message.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { Enum, Hex, Nullable, Status } from '@novasamatech/scale';
|
|
2
|
-
import {
|
|
1
|
+
import { Bytes, Enum, Hex, Nullable, Status } from '@novasamatech/scale';
|
|
2
|
+
import { Option, Struct, Vector, _void, compact, str, u64 } from 'scale-ts';
|
|
3
3
|
import { FileVariant } from './attachment.js';
|
|
4
4
|
const AccountIdCodec = Bytes(32);
|
|
5
|
-
const PublicKeyCodec = Bytes(
|
|
5
|
+
const PublicKeyCodec = Bytes(32);
|
|
6
6
|
export const TextContent = str;
|
|
7
7
|
export const RichTextContent = Struct({
|
|
8
8
|
text: Option(TextContent),
|
|
9
9
|
attachments: Option(Vector(FileVariant)),
|
|
10
10
|
});
|
|
11
|
-
|
|
11
|
+
// Byte ordinals are wire format — APPEND only, never reorder. `iOSVoIP` (2) is emitted by
|
|
12
|
+
// iOS PApp for VoIP push tokens; without it any envelope carrying one fails to decode with
|
|
13
|
+
// `Unknown status index: 2`.
|
|
14
|
+
export const Platform = Status('Android', 'iOS', 'iOSVoIP');
|
|
12
15
|
export const TokenContent = Struct({
|
|
13
16
|
token: Hex(),
|
|
14
17
|
platform: Platform,
|
|
@@ -1,100 +1,18 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
describe('
|
|
4
|
-
it('
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { DeviceInfoContent } from './message.js';
|
|
3
|
+
describe('DeviceInfoContent', () => {
|
|
4
|
+
it('round-trips a 32-byte X25519 encryption public key', () => {
|
|
5
|
+
const info = {
|
|
6
|
+
statementAccountId: new Uint8Array(32).fill(0xa1),
|
|
7
|
+
encryptionPublicKey: new Uint8Array(32).fill(0x04),
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
expect(decoded.purpose).toBe('AUDIO_CALL');
|
|
11
|
-
expect(decoded.sdp).toEqual(original.sdp);
|
|
9
|
+
expect(DeviceInfoContent.dec(DeviceInfoContent.enc(info))).toEqual(info);
|
|
12
10
|
});
|
|
13
|
-
it('
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
it('DataChannelIceCandidateContent round-trips', () => {
|
|
19
|
-
const original = { offerMessageId: 'offer-1', sdp: new Uint8Array([0xde, 0xad, 0xbe, 0xef]) };
|
|
20
|
-
const decoded = DataChannelIceCandidateContent.dec(DataChannelIceCandidateContent.enc(original));
|
|
21
|
-
expect(decoded).toEqual(original);
|
|
22
|
-
});
|
|
23
|
-
it('DataChannelClosedContent round-trips', () => {
|
|
24
|
-
const original = { offerMessageId: 'offer-1' };
|
|
25
|
-
const decoded = DataChannelClosedContent.dec(DataChannelClosedContent.enc(original));
|
|
26
|
-
expect(decoded).toEqual(original);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
describe('CoinagePaymentContent', () => {
|
|
30
|
-
it('round-trips with a small Balance and a couple of coin keys', () => {
|
|
31
|
-
// scale-ts `compact` decodes to `number` for values ≤ 2^30 and `bigint`
|
|
32
|
-
// for larger ones; normalise to BigInt before asserting.
|
|
33
|
-
const original = {
|
|
34
|
-
totalValue: 1_234_567,
|
|
35
|
-
coinKeys: [new Uint8Array(32).fill(0x11), new Uint8Array(32).fill(0x22)],
|
|
36
|
-
};
|
|
37
|
-
const decoded = CoinagePaymentContent.dec(CoinagePaymentContent.enc(original));
|
|
38
|
-
expect(BigInt(decoded.totalValue)).toBe(1234567n);
|
|
39
|
-
expect(decoded.coinKeys).toHaveLength(2);
|
|
40
|
-
expect(decoded.coinKeys[0]).toEqual(original.coinKeys[0]);
|
|
41
|
-
expect(decoded.coinKeys[1]).toEqual(original.coinKeys[1]);
|
|
42
|
-
});
|
|
43
|
-
it('round-trips a large Balance (forces bigint path)', () => {
|
|
44
|
-
const huge = 2n ** 100n;
|
|
45
|
-
const original = {
|
|
46
|
-
totalValue: huge,
|
|
47
|
-
coinKeys: [new Uint8Array(32).fill(0x33)],
|
|
48
|
-
};
|
|
49
|
-
const decoded = CoinagePaymentContent.dec(CoinagePaymentContent.enc(original));
|
|
50
|
-
expect(BigInt(decoded.totalValue)).toBe(huge);
|
|
51
|
-
});
|
|
52
|
-
it('round-trips with an empty coin-keys list', () => {
|
|
53
|
-
const original = { totalValue: 0, coinKeys: [] };
|
|
54
|
-
const decoded = CoinagePaymentContent.dec(CoinagePaymentContent.enc(original));
|
|
55
|
-
expect(BigInt(decoded.totalValue)).toBe(0n);
|
|
56
|
-
expect(decoded.coinKeys).toEqual([]);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
describe('MessageContent enum discriminants', () => {
|
|
60
|
-
it('coinagePayment lands on discriminant 16 and round-trips inside MessageContent', () => {
|
|
61
|
-
const value = {
|
|
62
|
-
tag: 'coinagePayment',
|
|
63
|
-
value: { totalValue: 42, coinKeys: [new Uint8Array(32).fill(0xab)] },
|
|
64
|
-
};
|
|
65
|
-
const encoded = MessageContent.enc(value);
|
|
66
|
-
expect(encoded[0]).toBe(16);
|
|
67
|
-
const decoded = MessageContent.dec(encoded);
|
|
68
|
-
expect(decoded.tag).toBe('coinagePayment');
|
|
69
|
-
if (decoded.tag !== 'coinagePayment')
|
|
70
|
-
throw new Error('unreachable');
|
|
71
|
-
expect(BigInt(decoded.value.totalValue)).toBe(42n);
|
|
72
|
-
expect(decoded.value.coinKeys[0]).toEqual(value.value.coinKeys[0]);
|
|
73
|
-
});
|
|
74
|
-
it('dataChannelClosed lands on discriminant 11 and round-trips inside MessageContent', () => {
|
|
75
|
-
const value = {
|
|
76
|
-
tag: 'dataChannelClosed',
|
|
77
|
-
value: { offerMessageId: 'offer-x' },
|
|
78
|
-
};
|
|
79
|
-
const encoded = MessageContent.enc(value);
|
|
80
|
-
expect(encoded[0]).toBe(11);
|
|
81
|
-
const decoded = MessageContent.dec(encoded);
|
|
82
|
-
expect(decoded.tag).toBe('dataChannelClosed');
|
|
83
|
-
if (decoded.tag !== 'dataChannelClosed')
|
|
84
|
-
throw new Error('unreachable');
|
|
85
|
-
expect(decoded.value.offerMessageId).toBe('offer-x');
|
|
86
|
-
});
|
|
87
|
-
it('dataChannelOffer lands on discriminant 8 and round-trips inside MessageContent', () => {
|
|
88
|
-
const value = {
|
|
89
|
-
tag: 'dataChannelOffer',
|
|
90
|
-
value: { sdp: new Uint8Array([1, 2, 3]), purpose: 'VIDEO_CALL' },
|
|
11
|
+
it('encodes to a fixed 64 bytes (32-byte accountId + 32-byte X25519 key)', () => {
|
|
12
|
+
const info = {
|
|
13
|
+
statementAccountId: new Uint8Array(32).fill(0xa1),
|
|
14
|
+
encryptionPublicKey: new Uint8Array(32).fill(0x04),
|
|
91
15
|
};
|
|
92
|
-
|
|
93
|
-
expect(encoded[0]).toBe(8);
|
|
94
|
-
const decoded = MessageContent.dec(encoded);
|
|
95
|
-
if (decoded.tag !== 'dataChannelOffer')
|
|
96
|
-
throw new Error('unreachable');
|
|
97
|
-
expect(decoded.value.purpose).toBe('VIDEO_CALL');
|
|
98
|
-
expect(decoded.value.sdp).toEqual(value.value.sdp);
|
|
16
|
+
expect(DeviceInfoContent.enc(info).length).toBe(64);
|
|
99
17
|
});
|
|
100
18
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novasamatech/host-chat",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.1",
|
|
5
5
|
"description": "Host statement store chat integration",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"README.md"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@novasamatech/scale": "0.
|
|
44
|
-
"@novasamatech/statement-store": "0.
|
|
45
|
-
"@novasamatech/storage-adapter": "0.
|
|
43
|
+
"@novasamatech/scale": "0.9.1",
|
|
44
|
+
"@novasamatech/statement-store": "0.9.1",
|
|
45
|
+
"@novasamatech/storage-adapter": "0.9.1",
|
|
46
46
|
"nanoid": "6.0.0",
|
|
47
47
|
"neverthrow": "^8.2.0"
|
|
48
48
|
},
|