@graphprotocol/hypergraph 0.0.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/LICENSE +21 -0
- package/README.md +2 -0
- package/dist/connect/auth-storage.d.ts.map +1 -0
- package/dist/connect/create-app-identity.d.ts.map +1 -0
- package/dist/connect/create-auth-url.d.ts.map +1 -0
- package/dist/connect/create-auth-url.js +35 -0
- package/dist/connect/create-auth-url.js.map +1 -0
- package/dist/connect/create-callback-params.d.ts.map +1 -0
- package/dist/connect/create-callback-params.js +17 -0
- package/dist/connect/create-callback-params.js.map +1 -0
- package/dist/connect/create-identity-keys.d.ts.map +1 -0
- package/dist/connect/identity-encryption.d.ts.map +1 -0
- package/dist/connect/index.d.ts.map +1 -0
- package/dist/connect/login.d.ts.map +1 -0
- package/dist/connect/parse-callback-params.d.ts.map +1 -0
- package/dist/connect/parse-callback-params.js +63 -0
- package/dist/connect/parse-callback-params.js.map +1 -0
- package/dist/connect/prove-ownership.d.ts.map +1 -0
- package/dist/connect/types.d.ts +57 -0
- package/dist/connect/types.d.ts.map +1 -0
- package/dist/connect/types.js +24 -0
- package/dist/connect/types.js.map +1 -0
- package/dist/entity/create.d.ts.map +1 -0
- package/dist/entity/decodedEntitiesCache.d.ts.map +1 -0
- package/dist/entity/delete.d.ts.map +1 -0
- package/dist/entity/entity.d.ts.map +1 -0
- package/dist/entity/entityRelationParentsMap.d.ts.map +1 -0
- package/dist/entity/findMany.d.ts.map +1 -0
- package/dist/entity/findMany.js +436 -0
- package/dist/entity/findMany.js.map +1 -0
- package/dist/entity/findOne.d.ts.map +1 -0
- package/dist/entity/getEntityRelations.d.ts.map +1 -0
- package/dist/entity/index.d.ts.map +1 -0
- package/dist/entity/relationParentsMap.d.ts.map +1 -0
- package/dist/entity/removeRelation.d.ts.map +1 -0
- package/dist/entity/types.d.ts +79 -0
- package/dist/entity/types.d.ts.map +1 -0
- package/dist/entity/types.js +2 -0
- package/dist/entity/types.js.map +1 -0
- package/dist/entity/update.d.ts.map +1 -0
- package/dist/identity/auth-storage.d.ts.map +1 -0
- package/dist/identity/get-verified-identity.d.ts.map +1 -0
- package/dist/identity/identity-encryption.d.ts.map +1 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/logout.d.ts.map +1 -0
- package/dist/identity/prove-ownership.d.ts.map +1 -0
- package/dist/inboxes/create-inbox.d.ts.map +1 -0
- package/dist/inboxes/get-list-inboxes.d.ts.map +1 -0
- package/dist/inboxes/index.d.ts.map +1 -0
- package/dist/inboxes/merge-messages.d.ts.map +1 -0
- package/dist/inboxes/message-encryption.d.ts.map +1 -0
- package/dist/inboxes/message-validation.d.ts.map +1 -0
- package/dist/inboxes/prepare-message.d.ts +31 -0
- package/dist/inboxes/prepare-message.d.ts.map +1 -0
- package/dist/inboxes/recover-inbox-creator.d.ts.map +1 -0
- package/dist/inboxes/recover-inbox-message-signer.d.ts.map +1 -0
- package/dist/inboxes/send-message.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/signed-update-message.d.ts.map +1 -0
- package/dist/messages/types.d.ts.map +1 -0
- package/dist/space-events/accept-invitation.d.ts.map +1 -0
- package/dist/space-events/apply-event.d.ts.map +1 -0
- package/dist/space-events/create-inbox.d.ts.map +1 -0
- package/dist/space-events/create-invitation.d.ts.map +1 -0
- package/dist/space-events/create-space.d.ts.map +1 -0
- package/dist/space-events/delete-space.d.ts.map +1 -0
- package/dist/space-events/hash-event.d.ts.map +1 -0
- package/dist/space-events/index.d.ts.map +1 -0
- package/dist/space-info/decrypt-space-info.d.ts.map +1 -0
- package/dist/space-info/encrypt-and-sign-space-info.d.ts.map +1 -0
- package/dist/space-info/index.d.ts.map +1 -0
- package/dist/store-connect.d.ts.map +1 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/type/type.d.ts.map +1 -0
- package/dist/utils/automergeId.d.ts +9 -0
- package/dist/utils/automergeId.d.ts.map +1 -0
- package/dist/utils/automergeId.js +17 -0
- package/dist/utils/automergeId.js.map +1 -0
- package/dist/utils/generateId.d.ts +15 -0
- package/dist/utils/generateId.d.ts.map +1 -0
- package/dist/utils/generateId.js +18 -0
- package/dist/utils/generateId.js.map +1 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/package.json +35 -0
- package/src/connect/auth-storage.ts +67 -0
- package/src/connect/create-app-identity.ts +16 -0
- package/src/connect/create-auth-url.ts +42 -0
- package/src/connect/create-callback-params.ts +30 -0
- package/src/connect/create-identity-keys.ts +20 -0
- package/src/connect/identity-encryption.ts +232 -0
- package/src/connect/index.ts +10 -0
- package/src/connect/login.ts +114 -0
- package/src/connect/parse-auth-params.ts +37 -0
- package/src/connect/parse-callback-params.ts +67 -0
- package/src/connect/prove-ownership.ts +58 -0
- package/src/connect/types.ts +67 -0
- package/src/entity/create.ts +58 -0
- package/src/entity/decodedEntitiesCache.ts +38 -0
- package/src/entity/delete.ts +52 -0
- package/src/entity/entity.ts +26 -0
- package/src/entity/entityRelationParentsMap.ts +6 -0
- package/src/entity/findMany.ts +506 -0
- package/src/entity/findOne.ts +34 -0
- package/src/entity/getEntityRelations.ts +45 -0
- package/src/entity/hasValidTypesProperty.ts +8 -0
- package/src/entity/index.ts +8 -0
- package/src/entity/relationParentsMap.ts +6 -0
- package/src/entity/removeRelation.ts +21 -0
- package/src/entity/test.ts +0 -0
- package/src/entity/types.ts +100 -0
- package/src/entity/update.ts +58 -0
- package/src/entity/variant-schema.ts +677 -0
- package/src/identity/auth-storage.ts +57 -0
- package/src/identity/get-verified-identity.ts +53 -0
- package/src/identity/identity-encryption.ts +140 -0
- package/src/identity/index.ts +6 -0
- package/src/identity/logout.ts +8 -0
- package/src/identity/prove-ownership.ts +58 -0
- package/src/identity/types.ts +44 -0
- package/src/inboxes/create-inbox.ts +102 -0
- package/src/inboxes/get-list-inboxes.ts +52 -0
- package/src/inboxes/index.ts +10 -0
- package/src/inboxes/merge-messages.ts +28 -0
- package/src/inboxes/message-encryption.ts +35 -0
- package/src/inboxes/message-validation.ts +66 -0
- package/src/inboxes/prepare-message.ts +85 -0
- package/src/inboxes/recover-inbox-creator.ts +29 -0
- package/src/inboxes/recover-inbox-message-signer.ts +42 -0
- package/src/inboxes/send-message.ts +75 -0
- package/src/inboxes/types.ts +9 -0
- package/src/index.ts +13 -0
- package/src/key/create-key.ts +27 -0
- package/src/key/decrypt-key.ts +19 -0
- package/src/key/encrypt-key.ts +27 -0
- package/src/key/index.ts +4 -0
- package/src/key/key-box.ts +31 -0
- package/src/messages/decrypt-message.ts +13 -0
- package/src/messages/encrypt-message.ts +14 -0
- package/src/messages/index.ts +5 -0
- package/src/messages/serialize.ts +24 -0
- package/src/messages/signed-update-message.ts +84 -0
- package/src/messages/types.ts +506 -0
- package/src/space-events/accept-invitation.ts +36 -0
- package/src/space-events/apply-event.ts +150 -0
- package/src/space-events/create-inbox.ts +56 -0
- package/src/space-events/create-invitation.ts +41 -0
- package/src/space-events/create-space.ts +35 -0
- package/src/space-events/delete-space.ts +36 -0
- package/src/space-events/hash-event.ts +10 -0
- package/src/space-events/index.ts +8 -0
- package/src/space-events/types.ts +137 -0
- package/src/space-info/decrypt-space-info.ts +22 -0
- package/src/space-info/encrypt-and-sign-space-info.ts +50 -0
- package/src/space-info/index.ts +3 -0
- package/src/space-info/types.ts +7 -0
- package/src/store-connect.ts +504 -0
- package/src/store.ts +493 -0
- package/src/type/type.ts +25 -0
- package/src/types.ts +47 -0
- package/src/utils/assertExhaustive.ts +3 -0
- package/src/utils/automergeId.ts +18 -0
- package/src/utils/base58.ts +74 -0
- package/src/utils/generateId.ts +18 -0
- package/src/utils/hexBytesAddressUtils.ts +25 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/internal/base58Utils.ts +47 -0
- package/src/utils/internal/deep-merge.ts +38 -0
- package/src/utils/isRelationField.ts +9 -0
- package/src/utils/jsc.ts +94 -0
- package/src/utils/stringToUint8Array.ts +9 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema';
|
|
2
|
+
|
|
3
|
+
import { InboxSenderAuthPolicy } from '../inboxes/types.js';
|
|
4
|
+
import {
|
|
5
|
+
AcceptInvitationEvent,
|
|
6
|
+
CreateInvitationEvent,
|
|
7
|
+
CreateSpaceEvent,
|
|
8
|
+
CreateSpaceInboxEvent,
|
|
9
|
+
SpaceEvent,
|
|
10
|
+
} from '../space-events/index.js';
|
|
11
|
+
import { SignatureWithRecovery } from '../types.js';
|
|
12
|
+
export const SignedUpdate = Schema.Struct({
|
|
13
|
+
update: Schema.Uint8Array,
|
|
14
|
+
accountAddress: Schema.String,
|
|
15
|
+
signature: SignatureWithRecovery,
|
|
16
|
+
updateId: Schema.String,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const Updates = Schema.Struct({
|
|
20
|
+
updates: Schema.Array(SignedUpdate),
|
|
21
|
+
firstUpdateClock: Schema.Number,
|
|
22
|
+
lastUpdateClock: Schema.Number,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export type Updates = Schema.Schema.Type<typeof Updates>;
|
|
26
|
+
|
|
27
|
+
export const KeyBox = Schema.Struct({
|
|
28
|
+
accountAddress: Schema.String,
|
|
29
|
+
ciphertext: Schema.String,
|
|
30
|
+
nonce: Schema.String,
|
|
31
|
+
authorPublicKey: Schema.String,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export type KeyBox = Schema.Schema.Type<typeof KeyBox>;
|
|
35
|
+
|
|
36
|
+
export const KeyBoxWithKeyId = Schema.Struct({
|
|
37
|
+
...KeyBox.fields,
|
|
38
|
+
id: Schema.String,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export type KeyBoxWithKeyId = Schema.Schema.Type<typeof KeyBoxWithKeyId>;
|
|
42
|
+
|
|
43
|
+
export const IdentityKeyBox = Schema.Struct({
|
|
44
|
+
accountAddress: Schema.String,
|
|
45
|
+
ciphertext: Schema.String,
|
|
46
|
+
nonce: Schema.String,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export type IdentityKeyBox = Schema.Schema.Type<typeof IdentityKeyBox>;
|
|
50
|
+
|
|
51
|
+
export const RequestCreateSpaceEvent = Schema.Struct({
|
|
52
|
+
type: Schema.Literal('create-space-event'),
|
|
53
|
+
spaceId: Schema.String,
|
|
54
|
+
event: CreateSpaceEvent,
|
|
55
|
+
keyBox: KeyBoxWithKeyId,
|
|
56
|
+
name: Schema.String,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export type RequestCreateSpaceEvent = Schema.Schema.Type<typeof RequestCreateSpaceEvent>;
|
|
60
|
+
|
|
61
|
+
export const RequestConnectCreateSpaceEvent = Schema.Struct({
|
|
62
|
+
type: Schema.Literal('connect-create-space-event'),
|
|
63
|
+
spaceId: Schema.String,
|
|
64
|
+
event: CreateSpaceEvent,
|
|
65
|
+
keyBox: KeyBoxWithKeyId,
|
|
66
|
+
infoContent: Schema.String,
|
|
67
|
+
infoSignature: SignatureWithRecovery,
|
|
68
|
+
name: Schema.String,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export type RequestConnectCreateSpaceEvent = Schema.Schema.Type<typeof RequestConnectCreateSpaceEvent>;
|
|
72
|
+
|
|
73
|
+
export const RequestCreateInvitationEvent = Schema.Struct({
|
|
74
|
+
type: Schema.Literal('create-invitation-event'),
|
|
75
|
+
spaceId: Schema.String,
|
|
76
|
+
event: CreateInvitationEvent,
|
|
77
|
+
keyBoxes: Schema.Array(KeyBoxWithKeyId),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export const RequestConnectAddAppIdentityToSpaces = Schema.Struct({
|
|
81
|
+
type: Schema.Literal('connect-add-app-identity-to-spaces'),
|
|
82
|
+
appIdentityAddress: Schema.String,
|
|
83
|
+
spacesInput: Schema.Array(
|
|
84
|
+
Schema.Struct({
|
|
85
|
+
id: Schema.String,
|
|
86
|
+
keyBoxes: Schema.Array(KeyBoxWithKeyId),
|
|
87
|
+
}),
|
|
88
|
+
),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export type RequestConnectAddAppIdentityToSpaces = Schema.Schema.Type<typeof RequestConnectAddAppIdentityToSpaces>;
|
|
92
|
+
|
|
93
|
+
export type RequestCreateInvitationEvent = Schema.Schema.Type<typeof RequestCreateInvitationEvent>;
|
|
94
|
+
|
|
95
|
+
export const RequestAcceptInvitationEvent = Schema.Struct({
|
|
96
|
+
type: Schema.Literal('accept-invitation-event'),
|
|
97
|
+
spaceId: Schema.String,
|
|
98
|
+
event: AcceptInvitationEvent,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export type RequestAcceptInvitationEvent = Schema.Schema.Type<typeof RequestAcceptInvitationEvent>;
|
|
102
|
+
|
|
103
|
+
export const RequestSubscribeToSpace = Schema.Struct({
|
|
104
|
+
type: Schema.Literal('subscribe-space'),
|
|
105
|
+
id: Schema.String,
|
|
106
|
+
lastKnownUpdateClock: Schema.optional(Schema.Number),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
export type RequestSubscribeToSpace = Schema.Schema.Type<typeof RequestSubscribeToSpace>;
|
|
110
|
+
|
|
111
|
+
export const RequestListSpaces = Schema.Struct({
|
|
112
|
+
type: Schema.Literal('list-spaces'),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
export type RequestListSpaces = Schema.Schema.Type<typeof RequestListSpaces>;
|
|
116
|
+
|
|
117
|
+
export const RequestListInvitations = Schema.Struct({
|
|
118
|
+
type: Schema.Literal('list-invitations'),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export type RequestListInvitations = Schema.Schema.Type<typeof RequestListInvitations>;
|
|
122
|
+
|
|
123
|
+
export const RequestCreateUpdate = Schema.Struct({
|
|
124
|
+
type: Schema.Literal('create-update'),
|
|
125
|
+
accountAddress: Schema.String,
|
|
126
|
+
update: Schema.Uint8Array,
|
|
127
|
+
spaceId: Schema.String,
|
|
128
|
+
updateId: Schema.String, // used to identify the confirmation message
|
|
129
|
+
signature: SignatureWithRecovery,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
export const RequestCreateAccountInbox = Schema.Struct({
|
|
133
|
+
type: Schema.Literal('create-account-inbox'),
|
|
134
|
+
accountAddress: Schema.String,
|
|
135
|
+
inboxId: Schema.String,
|
|
136
|
+
isPublic: Schema.Boolean,
|
|
137
|
+
authPolicy: InboxSenderAuthPolicy,
|
|
138
|
+
encryptionPublicKey: Schema.String,
|
|
139
|
+
signature: SignatureWithRecovery,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
export type RequestCreateAccountInbox = Schema.Schema.Type<typeof RequestCreateAccountInbox>;
|
|
143
|
+
|
|
144
|
+
export const RequestCreateSpaceInboxEvent = Schema.Struct({
|
|
145
|
+
type: Schema.Literal('create-space-inbox-event'),
|
|
146
|
+
spaceId: Schema.String,
|
|
147
|
+
event: CreateSpaceInboxEvent,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export type RequestCreateSpaceInboxEvent = Schema.Schema.Type<typeof RequestCreateSpaceInboxEvent>;
|
|
151
|
+
|
|
152
|
+
export const RequestGetLatestSpaceInboxMessages = Schema.Struct({
|
|
153
|
+
type: Schema.Literal('get-latest-space-inbox-messages'),
|
|
154
|
+
spaceId: Schema.String,
|
|
155
|
+
inboxId: Schema.String,
|
|
156
|
+
since: Schema.Date,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
export type RequestGetLatestSpaceInboxMessages = Schema.Schema.Type<typeof RequestGetLatestSpaceInboxMessages>;
|
|
160
|
+
|
|
161
|
+
export const RequestGetLatestAccountInboxMessages = Schema.Struct({
|
|
162
|
+
type: Schema.Literal('get-latest-account-inbox-messages'),
|
|
163
|
+
accountAddress: Schema.String,
|
|
164
|
+
inboxId: Schema.String,
|
|
165
|
+
since: Schema.Date,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
export type RequestGetLatestAccountInboxMessages = Schema.Schema.Type<typeof RequestGetLatestAccountInboxMessages>;
|
|
169
|
+
|
|
170
|
+
export const RequestGetAccountInboxes = Schema.Struct({
|
|
171
|
+
type: Schema.Literal('get-account-inboxes'),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export type RequestGetAccountInboxes = Schema.Schema.Type<typeof RequestGetAccountInboxes>;
|
|
175
|
+
|
|
176
|
+
export const RequestMessage = Schema.Union(
|
|
177
|
+
RequestCreateSpaceEvent,
|
|
178
|
+
RequestCreateInvitationEvent,
|
|
179
|
+
RequestAcceptInvitationEvent,
|
|
180
|
+
RequestSubscribeToSpace,
|
|
181
|
+
RequestListSpaces,
|
|
182
|
+
RequestListInvitations,
|
|
183
|
+
RequestCreateUpdate,
|
|
184
|
+
RequestCreateAccountInbox,
|
|
185
|
+
RequestCreateSpaceInboxEvent,
|
|
186
|
+
RequestGetLatestSpaceInboxMessages,
|
|
187
|
+
RequestGetLatestAccountInboxMessages,
|
|
188
|
+
RequestGetAccountInboxes,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
export type RequestMessage = Schema.Schema.Type<typeof RequestMessage>;
|
|
192
|
+
|
|
193
|
+
export type RequestCreateUpdate = Schema.Schema.Type<typeof RequestCreateUpdate>;
|
|
194
|
+
|
|
195
|
+
export const RequestLoginNonce = Schema.Struct({
|
|
196
|
+
accountAddress: Schema.String,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
export type RequestLoginNonce = Schema.Schema.Type<typeof RequestLoginNonce>;
|
|
200
|
+
|
|
201
|
+
export const RequestLogin = Schema.Struct({
|
|
202
|
+
accountAddress: Schema.String,
|
|
203
|
+
message: Schema.String,
|
|
204
|
+
signature: Schema.String,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
export type RequestLogin = Schema.Schema.Type<typeof RequestLogin>;
|
|
208
|
+
|
|
209
|
+
export const RequestLoginWithSigningKey = Schema.Struct({
|
|
210
|
+
accountAddress: Schema.String,
|
|
211
|
+
message: Schema.String,
|
|
212
|
+
publicKey: Schema.String,
|
|
213
|
+
signature: Schema.String,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
export type RequestLoginWithSigningKey = Schema.Schema.Type<typeof RequestLoginWithSigningKey>;
|
|
217
|
+
|
|
218
|
+
export const RequestCreateIdentity = Schema.Struct({
|
|
219
|
+
keyBox: IdentityKeyBox,
|
|
220
|
+
accountProof: Schema.String,
|
|
221
|
+
keyProof: Schema.String,
|
|
222
|
+
message: Schema.String,
|
|
223
|
+
signaturePublicKey: Schema.String,
|
|
224
|
+
encryptionPublicKey: Schema.String,
|
|
225
|
+
signature: Schema.String,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
export type RequestCreateIdentity = Schema.Schema.Type<typeof RequestCreateIdentity>;
|
|
229
|
+
|
|
230
|
+
export const RequestConnectCreateIdentity = Schema.Struct({
|
|
231
|
+
keyBox: IdentityKeyBox,
|
|
232
|
+
accountProof: Schema.String,
|
|
233
|
+
keyProof: Schema.String,
|
|
234
|
+
signaturePublicKey: Schema.String,
|
|
235
|
+
encryptionPublicKey: Schema.String,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
export type RequestConnectCreateIdentity = Schema.Schema.Type<typeof RequestConnectCreateIdentity>;
|
|
239
|
+
|
|
240
|
+
export const RequestConnectCreateAppIdentity = Schema.Struct({
|
|
241
|
+
appId: Schema.String,
|
|
242
|
+
address: Schema.String,
|
|
243
|
+
ciphertext: Schema.String,
|
|
244
|
+
nonce: Schema.String,
|
|
245
|
+
signaturePublicKey: Schema.String,
|
|
246
|
+
encryptionPublicKey: Schema.String,
|
|
247
|
+
accountProof: Schema.String,
|
|
248
|
+
keyProof: Schema.String,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
export type RequestConnectCreateAppIdentity = Schema.Schema.Type<typeof RequestConnectCreateAppIdentity>;
|
|
252
|
+
|
|
253
|
+
export const ResponseConnectCreateIdentity = Schema.Struct({
|
|
254
|
+
success: Schema.Boolean,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
export type ResponseConnectCreateIdentity = Schema.Schema.Type<typeof ResponseConnectCreateIdentity>;
|
|
258
|
+
|
|
259
|
+
export const RequestCreateSpaceInboxMessage = Schema.Struct({
|
|
260
|
+
ciphertext: Schema.String,
|
|
261
|
+
signature: Schema.optional(SignatureWithRecovery),
|
|
262
|
+
authorAccountAddress: Schema.optional(Schema.String),
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
export type RequestCreateSpaceInboxMessage = Schema.Schema.Type<typeof RequestCreateSpaceInboxMessage>;
|
|
266
|
+
|
|
267
|
+
export const RequestCreateAccountInboxMessage = Schema.Struct({
|
|
268
|
+
ciphertext: Schema.String,
|
|
269
|
+
signature: Schema.optional(SignatureWithRecovery),
|
|
270
|
+
authorAccountAddress: Schema.optional(Schema.String),
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
export type RequestCreateAccountInboxMessage = Schema.Schema.Type<typeof RequestCreateAccountInboxMessage>;
|
|
274
|
+
|
|
275
|
+
export const ResponseListSpaces = Schema.Struct({
|
|
276
|
+
type: Schema.Literal('list-spaces'),
|
|
277
|
+
spaces: Schema.Array(
|
|
278
|
+
Schema.Struct({
|
|
279
|
+
id: Schema.String,
|
|
280
|
+
}),
|
|
281
|
+
),
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
export type ResponseListSpaces = Schema.Schema.Type<typeof ResponseListSpaces>;
|
|
285
|
+
|
|
286
|
+
export const Invitation = Schema.Struct({
|
|
287
|
+
id: Schema.String,
|
|
288
|
+
previousEventHash: Schema.String,
|
|
289
|
+
spaceId: Schema.String,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
export type Invitation = Schema.Schema.Type<typeof Invitation>;
|
|
293
|
+
|
|
294
|
+
export const ResponseListInvitations = Schema.Struct({
|
|
295
|
+
type: Schema.Literal('list-invitations'),
|
|
296
|
+
invitations: Schema.Array(Invitation),
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
export type ResponseListInvitations = Schema.Schema.Type<typeof ResponseListInvitations>;
|
|
300
|
+
|
|
301
|
+
export const ResponseSpaceEvent = Schema.Struct({
|
|
302
|
+
type: Schema.Literal('space-event'),
|
|
303
|
+
spaceId: Schema.String,
|
|
304
|
+
event: SpaceEvent,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
export type ResponseSpaceEvent = Schema.Schema.Type<typeof ResponseSpaceEvent>;
|
|
308
|
+
|
|
309
|
+
export const InboxMessage = Schema.Struct({
|
|
310
|
+
id: Schema.String,
|
|
311
|
+
ciphertext: Schema.String,
|
|
312
|
+
signature: Schema.optional(SignatureWithRecovery),
|
|
313
|
+
authorAccountAddress: Schema.optional(Schema.String),
|
|
314
|
+
createdAt: Schema.Date,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
export type InboxMessage = Schema.Schema.Type<typeof InboxMessage>;
|
|
318
|
+
|
|
319
|
+
export const SpaceInbox = Schema.Struct({
|
|
320
|
+
inboxId: Schema.String,
|
|
321
|
+
isPublic: Schema.Boolean,
|
|
322
|
+
authPolicy: InboxSenderAuthPolicy,
|
|
323
|
+
encryptionPublicKey: Schema.String,
|
|
324
|
+
secretKey: Schema.String,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
export type SpaceInbox = Schema.Schema.Type<typeof SpaceInbox>;
|
|
328
|
+
|
|
329
|
+
export const AccountInbox = Schema.Struct({
|
|
330
|
+
accountAddress: Schema.String,
|
|
331
|
+
inboxId: Schema.String,
|
|
332
|
+
isPublic: Schema.Boolean,
|
|
333
|
+
authPolicy: InboxSenderAuthPolicy,
|
|
334
|
+
encryptionPublicKey: Schema.String,
|
|
335
|
+
signature: SignatureWithRecovery,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
export type AccountInbox = Schema.Schema.Type<typeof AccountInbox>;
|
|
339
|
+
|
|
340
|
+
export const ResponseAccountInbox = Schema.Struct({
|
|
341
|
+
type: Schema.Literal('account-inbox'),
|
|
342
|
+
inbox: AccountInbox,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
export type ResponseAccountInbox = Schema.Schema.Type<typeof ResponseAccountInbox>;
|
|
346
|
+
|
|
347
|
+
export const ResponseSpace = Schema.Struct({
|
|
348
|
+
type: Schema.Literal('space'),
|
|
349
|
+
id: Schema.String,
|
|
350
|
+
events: Schema.Array(SpaceEvent),
|
|
351
|
+
keyBoxes: Schema.Array(KeyBoxWithKeyId),
|
|
352
|
+
updates: Schema.optional(Updates),
|
|
353
|
+
inboxes: Schema.Array(SpaceInbox),
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
export type ResponseSpace = Schema.Schema.Type<typeof ResponseSpace>;
|
|
357
|
+
|
|
358
|
+
export const ResponseUpdateConfirmed = Schema.Struct({
|
|
359
|
+
type: Schema.Literal('update-confirmed'),
|
|
360
|
+
updateId: Schema.String,
|
|
361
|
+
clock: Schema.Number,
|
|
362
|
+
spaceId: Schema.String,
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
export type ResponseUpdateConfirmed = Schema.Schema.Type<typeof ResponseUpdateConfirmed>;
|
|
366
|
+
|
|
367
|
+
export const ResponseUpdatesNotification = Schema.Struct({
|
|
368
|
+
type: Schema.Literal('updates-notification'),
|
|
369
|
+
updates: Updates,
|
|
370
|
+
spaceId: Schema.String,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
export type ResponseUpdatesNotification = Schema.Schema.Type<typeof ResponseUpdatesNotification>;
|
|
374
|
+
|
|
375
|
+
export const ResponseSpaceInboxMessage = Schema.Struct({
|
|
376
|
+
type: Schema.Literal('space-inbox-message'),
|
|
377
|
+
spaceId: Schema.String,
|
|
378
|
+
inboxId: Schema.String,
|
|
379
|
+
message: InboxMessage,
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
export type ResponseSpaceInboxMessage = Schema.Schema.Type<typeof ResponseSpaceInboxMessage>;
|
|
383
|
+
|
|
384
|
+
export const ResponseSpaceInboxMessages = Schema.Struct({
|
|
385
|
+
type: Schema.Literal('space-inbox-messages'),
|
|
386
|
+
spaceId: Schema.String,
|
|
387
|
+
inboxId: Schema.String,
|
|
388
|
+
messages: Schema.Array(InboxMessage),
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
export type ResponseSpaceInboxMessages = Schema.Schema.Type<typeof ResponseSpaceInboxMessages>;
|
|
392
|
+
|
|
393
|
+
export const ResponseAccountInboxMessage = Schema.Struct({
|
|
394
|
+
type: Schema.Literal('account-inbox-message'),
|
|
395
|
+
accountAddress: Schema.String,
|
|
396
|
+
inboxId: Schema.String,
|
|
397
|
+
message: InboxMessage,
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
export type ResponseAccountInboxMessage = Schema.Schema.Type<typeof ResponseAccountInboxMessage>;
|
|
401
|
+
|
|
402
|
+
export const ResponseAccountInboxMessages = Schema.Struct({
|
|
403
|
+
type: Schema.Literal('account-inbox-messages'),
|
|
404
|
+
accountAddress: Schema.String,
|
|
405
|
+
inboxId: Schema.String,
|
|
406
|
+
messages: Schema.Array(InboxMessage),
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
export type ResponseAccountInboxMessages = Schema.Schema.Type<typeof ResponseAccountInboxMessages>;
|
|
410
|
+
|
|
411
|
+
export const ResponseAccountInboxes = Schema.Struct({
|
|
412
|
+
type: Schema.Literal('account-inboxes'),
|
|
413
|
+
inboxes: Schema.Array(AccountInbox),
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
export type ResponseAccountInboxes = Schema.Schema.Type<typeof ResponseAccountInboxes>;
|
|
417
|
+
|
|
418
|
+
export const ResponseMessage = Schema.Union(
|
|
419
|
+
ResponseListSpaces,
|
|
420
|
+
ResponseListInvitations,
|
|
421
|
+
ResponseSpace,
|
|
422
|
+
ResponseSpaceEvent,
|
|
423
|
+
ResponseUpdateConfirmed,
|
|
424
|
+
ResponseUpdatesNotification,
|
|
425
|
+
ResponseAccountInbox,
|
|
426
|
+
ResponseSpaceInboxMessage,
|
|
427
|
+
ResponseSpaceInboxMessages,
|
|
428
|
+
ResponseAccountInboxMessage,
|
|
429
|
+
ResponseAccountInboxMessages,
|
|
430
|
+
ResponseAccountInboxes,
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
export type ResponseMessage = Schema.Schema.Type<typeof ResponseMessage>;
|
|
434
|
+
|
|
435
|
+
export const ResponseIdentityEncrypted = Schema.Struct({
|
|
436
|
+
keyBox: IdentityKeyBox,
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
export type ResponseIdentityEncrypted = Schema.Schema.Type<typeof ResponseIdentityEncrypted>;
|
|
440
|
+
|
|
441
|
+
export const ResponseIdentity = Schema.Struct({
|
|
442
|
+
accountAddress: Schema.String,
|
|
443
|
+
signaturePublicKey: Schema.String,
|
|
444
|
+
encryptionPublicKey: Schema.String,
|
|
445
|
+
accountProof: Schema.String,
|
|
446
|
+
keyProof: Schema.String,
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
export type ResponseIdentity = Schema.Schema.Type<typeof ResponseIdentity>;
|
|
450
|
+
|
|
451
|
+
export const SpaceInboxPublic = Schema.Struct({
|
|
452
|
+
inboxId: Schema.String,
|
|
453
|
+
isPublic: Schema.Boolean,
|
|
454
|
+
authPolicy: InboxSenderAuthPolicy,
|
|
455
|
+
encryptionPublicKey: Schema.String,
|
|
456
|
+
creationEvent: CreateSpaceInboxEvent,
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
export type SpaceInboxPublic = Schema.Schema.Type<typeof SpaceInboxPublic>;
|
|
460
|
+
|
|
461
|
+
export const ResponseSpaceInboxPublic = Schema.Struct({
|
|
462
|
+
inbox: SpaceInboxPublic,
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
export type ResponseSpaceInboxPublic = Schema.Schema.Type<typeof ResponseSpaceInboxPublic>;
|
|
466
|
+
|
|
467
|
+
export const ResponseListSpaceInboxesPublic = Schema.Struct({
|
|
468
|
+
inboxes: Schema.Array(SpaceInboxPublic),
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
export type ResponseListSpaceInboxesPublic = Schema.Schema.Type<typeof ResponseListSpaceInboxesPublic>;
|
|
472
|
+
|
|
473
|
+
export const AccountInboxPublic = Schema.Struct({
|
|
474
|
+
accountAddress: Schema.String,
|
|
475
|
+
inboxId: Schema.String,
|
|
476
|
+
isPublic: Schema.Boolean,
|
|
477
|
+
authPolicy: InboxSenderAuthPolicy,
|
|
478
|
+
encryptionPublicKey: Schema.String,
|
|
479
|
+
signature: SignatureWithRecovery,
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
export type AccountInboxPublic = Schema.Schema.Type<typeof AccountInboxPublic>;
|
|
483
|
+
|
|
484
|
+
export const ResponseAccountInboxPublic = Schema.Struct({
|
|
485
|
+
inbox: AccountInboxPublic,
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
export type ResponseAccountInboxPublic = Schema.Schema.Type<typeof ResponseAccountInboxPublic>;
|
|
489
|
+
|
|
490
|
+
export const ResponseListAccountInboxesPublic = Schema.Struct({
|
|
491
|
+
inboxes: Schema.Array(AccountInboxPublic),
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
export type ResponseListAccountInboxesPublic = Schema.Schema.Type<typeof ResponseListAccountInboxesPublic>;
|
|
495
|
+
|
|
496
|
+
export const ResponseIdentityNotFoundError = Schema.Struct({
|
|
497
|
+
accountAddress: Schema.String,
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
export type ResponseIdentityNotFoundError = Schema.Schema.Type<typeof ResponseIdentityNotFoundError>;
|
|
501
|
+
|
|
502
|
+
export const ResponseIdentityExistsError = Schema.Struct({
|
|
503
|
+
accountAddress: Schema.String,
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
export type ResponseIdentityExistsError = Schema.Schema.Type<typeof ResponseIdentityExistsError>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
2
|
+
import { Effect } from 'effect';
|
|
3
|
+
|
|
4
|
+
import { canonicalize, generateId, hexToBytes, stringToUint8Array } from '../utils/index.js';
|
|
5
|
+
import type { AcceptInvitationEvent, Author } from './types.js';
|
|
6
|
+
|
|
7
|
+
type Params = {
|
|
8
|
+
author: Author;
|
|
9
|
+
previousEventHash: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const acceptInvitation = ({
|
|
13
|
+
author,
|
|
14
|
+
previousEventHash,
|
|
15
|
+
}: Params): Effect.Effect<AcceptInvitationEvent, undefined> => {
|
|
16
|
+
const transaction = {
|
|
17
|
+
id: generateId(),
|
|
18
|
+
type: 'accept-invitation' as const,
|
|
19
|
+
previousEventHash,
|
|
20
|
+
};
|
|
21
|
+
const encodedTransaction = stringToUint8Array(canonicalize(transaction));
|
|
22
|
+
const signatureResult = secp256k1.sign(encodedTransaction, hexToBytes(author.signaturePrivateKey), {
|
|
23
|
+
prehash: true,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return Effect.succeed({
|
|
27
|
+
transaction,
|
|
28
|
+
author: {
|
|
29
|
+
accountAddress: author.accountAddress,
|
|
30
|
+
signature: {
|
|
31
|
+
hex: signatureResult.toCompactHex(),
|
|
32
|
+
recovery: signatureResult.recovery,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
+
import { Effect, Schema } from 'effect';
|
|
4
|
+
import type { InvalidIdentityError, PublicIdentity } from '../identity/types.js';
|
|
5
|
+
import { canonicalize, stringToUint8Array } from '../utils/index.js';
|
|
6
|
+
import { hashEvent } from './hash-event.js';
|
|
7
|
+
import {
|
|
8
|
+
type ApplyError,
|
|
9
|
+
InvalidEventError,
|
|
10
|
+
SpaceEvent,
|
|
11
|
+
type SpaceInbox,
|
|
12
|
+
type SpaceInvitation,
|
|
13
|
+
type SpaceMember,
|
|
14
|
+
type SpaceState,
|
|
15
|
+
VerifySignatureError,
|
|
16
|
+
} from './types.js';
|
|
17
|
+
|
|
18
|
+
type Params = {
|
|
19
|
+
state: SpaceState | undefined;
|
|
20
|
+
event: SpaceEvent;
|
|
21
|
+
getVerifiedIdentity: (accountAddress: string) => Effect.Effect<PublicIdentity, InvalidIdentityError>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const decodeSpaceEvent = Schema.decodeUnknownEither(SpaceEvent);
|
|
25
|
+
|
|
26
|
+
export const applyEvent = ({
|
|
27
|
+
state,
|
|
28
|
+
event: rawEvent,
|
|
29
|
+
getVerifiedIdentity,
|
|
30
|
+
}: Params): Effect.Effect<SpaceState, ApplyError> => {
|
|
31
|
+
const decodedEvent = decodeSpaceEvent(rawEvent);
|
|
32
|
+
if (decodedEvent._tag === 'Left') {
|
|
33
|
+
return decodedEvent.left;
|
|
34
|
+
}
|
|
35
|
+
const event = decodedEvent.right;
|
|
36
|
+
|
|
37
|
+
if (event.transaction.type !== 'create-space') {
|
|
38
|
+
if (state === undefined) {
|
|
39
|
+
return Effect.fail(new InvalidEventError());
|
|
40
|
+
}
|
|
41
|
+
if (event.transaction.previousEventHash !== state.lastEventHash) {
|
|
42
|
+
return Effect.fail(new InvalidEventError());
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const encodedTransaction = stringToUint8Array(canonicalize(event.transaction));
|
|
47
|
+
|
|
48
|
+
let signatureInstance = secp256k1.Signature.fromCompact(event.author.signature.hex);
|
|
49
|
+
signatureInstance = signatureInstance.addRecoveryBit(event.author.signature.recovery);
|
|
50
|
+
const authorPublicKey = `0x${signatureInstance.recoverPublicKey(sha256(encodedTransaction)).toHex()}`;
|
|
51
|
+
|
|
52
|
+
return Effect.gen(function* () {
|
|
53
|
+
const identity = yield* getVerifiedIdentity(event.author.accountAddress);
|
|
54
|
+
if (authorPublicKey !== identity.signaturePublicKey) {
|
|
55
|
+
yield* Effect.fail(new VerifySignatureError());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let id = '';
|
|
59
|
+
let members: { [accountAddress: string]: SpaceMember } = {};
|
|
60
|
+
let removedMembers: { [accountAddress: string]: SpaceMember } = {};
|
|
61
|
+
let invitations: { [id: string]: SpaceInvitation } = {};
|
|
62
|
+
let inboxes: { [inboxId: string]: SpaceInbox } = {};
|
|
63
|
+
if (event.transaction.type === 'create-space') {
|
|
64
|
+
id = event.transaction.id;
|
|
65
|
+
members[event.transaction.creatorAccountAddress] = {
|
|
66
|
+
accountAddress: event.transaction.creatorAccountAddress,
|
|
67
|
+
role: 'admin',
|
|
68
|
+
};
|
|
69
|
+
} else if (state !== undefined) {
|
|
70
|
+
id = state.id;
|
|
71
|
+
members = { ...state.members };
|
|
72
|
+
removedMembers = { ...state.removedMembers };
|
|
73
|
+
invitations = { ...state.invitations };
|
|
74
|
+
inboxes = { ...state.inboxes };
|
|
75
|
+
if (event.transaction.type === 'accept-invitation') {
|
|
76
|
+
// is already a member
|
|
77
|
+
if (members[event.author.accountAddress] !== undefined) {
|
|
78
|
+
yield* Effect.fail(new InvalidEventError());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// find the invitation
|
|
82
|
+
const result = Object.entries(invitations).find(
|
|
83
|
+
([, invitation]) => invitation.inviteeAccountAddress === event.author.accountAddress,
|
|
84
|
+
);
|
|
85
|
+
if (!result) {
|
|
86
|
+
yield* Effect.fail(new InvalidEventError());
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// @ts-expect-error type issue? we checked that result is not undefined before
|
|
90
|
+
const [id, invitation] = result;
|
|
91
|
+
|
|
92
|
+
members[invitation.inviteeAccountAddress] = {
|
|
93
|
+
accountAddress: invitation.inviteeAccountAddress,
|
|
94
|
+
role: 'member',
|
|
95
|
+
};
|
|
96
|
+
delete invitations[id];
|
|
97
|
+
if (removedMembers[event.author.accountAddress] !== undefined) {
|
|
98
|
+
delete removedMembers[event.author.accountAddress];
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
// check if the author is an admin
|
|
102
|
+
if (members[event.author.accountAddress]?.role !== 'admin') {
|
|
103
|
+
yield* Effect.fail(new InvalidEventError());
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (event.transaction.type === 'delete-space') {
|
|
107
|
+
removedMembers = { ...members };
|
|
108
|
+
members = {};
|
|
109
|
+
invitations = {};
|
|
110
|
+
} else if (event.transaction.type === 'create-invitation') {
|
|
111
|
+
if (members[event.transaction.inviteeAccountAddress] !== undefined) {
|
|
112
|
+
yield* Effect.fail(new InvalidEventError());
|
|
113
|
+
}
|
|
114
|
+
for (const invitation of Object.values(invitations)) {
|
|
115
|
+
if (invitation.inviteeAccountAddress === event.transaction.inviteeAccountAddress) {
|
|
116
|
+
yield* Effect.fail(new InvalidEventError());
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
invitations[event.transaction.id] = {
|
|
121
|
+
inviteeAccountAddress: event.transaction.inviteeAccountAddress,
|
|
122
|
+
};
|
|
123
|
+
} else if (event.transaction.type === 'create-space-inbox') {
|
|
124
|
+
if (inboxes[event.transaction.inboxId] !== undefined) {
|
|
125
|
+
yield* Effect.fail(new InvalidEventError());
|
|
126
|
+
}
|
|
127
|
+
inboxes[event.transaction.inboxId] = {
|
|
128
|
+
inboxId: event.transaction.inboxId,
|
|
129
|
+
encryptionPublicKey: event.transaction.encryptionPublicKey,
|
|
130
|
+
isPublic: event.transaction.isPublic,
|
|
131
|
+
authPolicy: event.transaction.authPolicy,
|
|
132
|
+
secretKey: event.transaction.secretKey,
|
|
133
|
+
};
|
|
134
|
+
} else {
|
|
135
|
+
// state is required for all events except create-space
|
|
136
|
+
yield* Effect.fail(new InvalidEventError());
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
id,
|
|
143
|
+
members,
|
|
144
|
+
removedMembers,
|
|
145
|
+
invitations,
|
|
146
|
+
inboxes,
|
|
147
|
+
lastEventHash: hashEvent(event),
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
};
|