@derec-alliance/react-native 0.0.2 → 0.0.4
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/README.md +46 -2
- package/android/src/main/jniLibs/arm64-v8a/libderec_library.a +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libderec_library.a +0 -0
- package/android/src/main/jniLibs/x86_64/libderec_library.a +0 -0
- package/cpp/Primitives.cpp +27 -18
- package/cpp/ProtocolHost.cpp +37 -0
- package/cpp/StoreCallbacks.cpp +127 -19
- package/cpp/derec_ffi.h +145 -24
- package/ios/DeRecFFI.xcframework/ios-arm64/Headers/derec_ffi.h +145 -24
- package/ios/DeRecFFI.xcframework/ios-arm64/libderec_library.a +0 -0
- package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/Headers/derec_ffi.h +145 -24
- package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/libderec_library.a +2 -2
- package/lib/primitives.d.ts +9 -9
- package/lib/primitives.js +63 -13
- package/lib/protocol.d.ts +85 -6
- package/lib/protocol.js +119 -8
- package/lib/types.d.ts +313 -29
- package/lib/types.js +109 -2
- package/package.json +2 -1
- package/src/primitives.ts +77 -21
- package/src/protocol.ts +138 -13
- package/src/types.ts +379 -35
package/lib/types.js
CHANGED
|
@@ -3,6 +3,113 @@
|
|
|
3
3
|
// Copyright (c) 2026 DeRec Alliance. All rights reserved.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.FlowKind = exports.ContactMode = exports.SenderKind = void 0;
|
|
6
|
+
exports.channelFilterMatches = channelFilterMatches;
|
|
7
|
+
exports.advertisedEndpoints = advertisedEndpoints;
|
|
8
|
+
exports.sequentialFailover = sequentialFailover;
|
|
9
|
+
exports.singleEndpointTransport = singleEndpointTransport;
|
|
10
|
+
/**
|
|
11
|
+
* Whether a channel or member with these attributes survives `filter`.
|
|
12
|
+
*
|
|
13
|
+
* Every empty field means "do not restrict", `exclude` is applied after `ids`,
|
|
14
|
+
* and the restrictions combine with AND — the same contract the core states on
|
|
15
|
+
* `ChannelFilter`. A store whose backing cannot express the filter as a query
|
|
16
|
+
* can list and call this; that is correct but transfers the rows the filter
|
|
17
|
+
* exists to leave behind.
|
|
18
|
+
*
|
|
19
|
+
* `id` is a decimal string, as ids are everywhere on this bridge. `role` is the
|
|
20
|
+
* peer's `SenderKind` name for `listHelpers` and the member's `ReplicaRole`
|
|
21
|
+
* name for `listReplicas`.
|
|
22
|
+
*/
|
|
23
|
+
function channelFilterMatches(filter, id, status, role) {
|
|
24
|
+
if (!filter)
|
|
25
|
+
return true;
|
|
26
|
+
const ids = filter.ids ?? [];
|
|
27
|
+
const statuses = filter.status ?? [];
|
|
28
|
+
const exclude = filter.exclude ?? [];
|
|
29
|
+
if (ids.length > 0 && !ids.includes(id))
|
|
30
|
+
return false;
|
|
31
|
+
if (statuses.length > 0 && !statuses.includes(status))
|
|
32
|
+
return false;
|
|
33
|
+
if (filter.role != null && filter.role !== role)
|
|
34
|
+
return false;
|
|
35
|
+
return !exclude.includes(id);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The endpoints a peer-supplied message advertises, in the peer's own order.
|
|
39
|
+
*
|
|
40
|
+
* Yields `supported_transports` when it is non-empty, and otherwise the
|
|
41
|
+
* singular `transport_protocol` — which is how every implementation predating
|
|
42
|
+
* the offer list advertises, and the reason this is a function rather than a
|
|
43
|
+
* field read. Reading `transport_protocol` directly is a bug: its meaning
|
|
44
|
+
* narrowed to "one entry of a list, and possibly absent", so a peer that has
|
|
45
|
+
* moved past it looks unreachable to a reader that was correct before 0.0.3.
|
|
46
|
+
*
|
|
47
|
+
* Reports what was advertised, not what is acceptable — nothing here is
|
|
48
|
+
* validated, and the protocol still applies its own transport policy to
|
|
49
|
+
* whatever it records.
|
|
50
|
+
*/
|
|
51
|
+
function advertisedEndpoints(message) {
|
|
52
|
+
if (!message)
|
|
53
|
+
return [];
|
|
54
|
+
const offers = message.supported_transports ?? [];
|
|
55
|
+
if (offers.length > 0)
|
|
56
|
+
return offers;
|
|
57
|
+
return message.transport_protocol ? [message.transport_protocol] : [];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Builds a {@link Transport} that tries each endpoint in the order the peer
|
|
61
|
+
* offered it and stops at the first success.
|
|
62
|
+
*
|
|
63
|
+
* An error is thrown only when every endpoint failed. The message is delivered
|
|
64
|
+
* at most once.
|
|
65
|
+
*
|
|
66
|
+
* This is the right default. A peer advertising several endpoints is saying it
|
|
67
|
+
* can be reached at any of them, and the reason 0.0.3 records the whole list is
|
|
68
|
+
* so one being down does not end the conversation.
|
|
69
|
+
*/
|
|
70
|
+
function sequentialFailover(dialer) {
|
|
71
|
+
return {
|
|
72
|
+
async send(endpoints, message) {
|
|
73
|
+
let last;
|
|
74
|
+
for (const endpoint of endpoints) {
|
|
75
|
+
try {
|
|
76
|
+
await dialer(endpoint, message);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
last = e;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// `endpoints` is never empty — the library refuses to record a peer
|
|
84
|
+
// whose endpoints were all filtered away — so reaching here means at
|
|
85
|
+
// least one attempt was made and `last` is populated.
|
|
86
|
+
throw last ?? new Error('send was called with no endpoints');
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Builds a {@link Transport} that uses the first endpoint only.
|
|
92
|
+
*
|
|
93
|
+
* Reproduces the pre-0.0.3 behaviour exactly, for an application that genuinely
|
|
94
|
+
* serves one endpoint or has a reason not to fail over.
|
|
95
|
+
*
|
|
96
|
+
* It exists so that choosing it is visible. `endpoints[0]` written inline looks
|
|
97
|
+
* like an implementation detail and reads as finished; naming this records that
|
|
98
|
+
* failover was considered and declined, which is a claim a reviewer can
|
|
99
|
+
* disagree with. If the peers this application talks to advertise more than one
|
|
100
|
+
* endpoint, prefer {@link sequentialFailover} — every endpoint after the first
|
|
101
|
+
* is reachability being thrown away.
|
|
102
|
+
*/
|
|
103
|
+
function singleEndpointTransport(dialer) {
|
|
104
|
+
return {
|
|
105
|
+
async send(endpoints, message) {
|
|
106
|
+
if (endpoints.length === 0) {
|
|
107
|
+
throw new Error('send was called with no endpoints');
|
|
108
|
+
}
|
|
109
|
+
await dialer(endpoints[0], message);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
6
113
|
var SenderKind;
|
|
7
114
|
(function (SenderKind) {
|
|
8
115
|
SenderKind[SenderKind["Owner"] = 0] = "Owner";
|
|
@@ -54,10 +161,10 @@ var FlowKind;
|
|
|
54
161
|
/** Ask the replica group whether this device is behind, and catch up if it
|
|
55
162
|
* is. Replica-only, and takes no parameters — the group and this device's
|
|
56
163
|
* own version both come from the stores. */
|
|
57
|
-
FlowKind[FlowKind["
|
|
164
|
+
FlowKind[FlowKind["ReplicaDiscovery"] = 7] = "ReplicaDiscovery";
|
|
58
165
|
/** Remove a member from the replica group. Replica-only. Naming this device
|
|
59
166
|
* is a voluntary departure; naming another is an eviction. Params:
|
|
60
167
|
* `{ replica_id: string; memo?: string }` — `replica_id` is a decimal
|
|
61
168
|
* string so ids above 2^53 survive JS number handling. */
|
|
62
|
-
FlowKind[FlowKind["
|
|
169
|
+
FlowKind[FlowKind["UnpairReplica"] = 8] = "UnpairReplica";
|
|
63
170
|
})(FlowKind || (exports.FlowKind = FlowKind = {}));
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@derec-alliance/react-native",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "React Native bindings for derec-library, the Rust SDK for the DeRec protocol.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/derecalliance/lib-derec"
|
|
9
9
|
},
|
|
10
|
+
"homepage": "https://derec.org",
|
|
10
11
|
"main": "lib/index.js",
|
|
11
12
|
"types": "lib/index.d.ts",
|
|
12
13
|
"files": [
|
package/src/primitives.ts
CHANGED
|
@@ -86,11 +86,11 @@ function bytes(value: unknown): Uint8Array {
|
|
|
86
86
|
return new Uint8Array(value as ArrayBuffer);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
function replyTo(value: TransportProtocol |
|
|
93
|
-
return
|
|
89
|
+
/** An omitted or empty list means "no override" for every reply-to argument;
|
|
90
|
+
* the C ABI reads a zero-length buffer as absent, and the responder then
|
|
91
|
+
* routes to the endpoints already recorded for the channel. */
|
|
92
|
+
function replyTo(value: TransportProtocol[] | undefined): Uint8Array {
|
|
93
|
+
return value && value.length > 0 ? encodeTransportList(value) : new Uint8Array(0);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
@@ -117,7 +117,7 @@ const discovery = {
|
|
|
117
117
|
produce(
|
|
118
118
|
channel_id: bigint,
|
|
119
119
|
shared_key: Uint8Array,
|
|
120
|
-
reply_to?: TransportProtocol
|
|
120
|
+
reply_to?: TransportProtocol[],
|
|
121
121
|
): ProduceResult {
|
|
122
122
|
const envelope = call(
|
|
123
123
|
'produce_get_secret_ids_versions_request_message',
|
|
@@ -188,12 +188,69 @@ const discovery = {
|
|
|
188
188
|
},
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Frames a preference-ordered endpoint list for the native seam: each entry
|
|
193
|
+
* preceded by its protobuf varint byte length. Order is preserved exactly.
|
|
194
|
+
*/
|
|
195
|
+
function encodeTransportList(transports: TransportProtocol[]): Uint8Array {
|
|
196
|
+
const entries = transports.map((t) =>
|
|
197
|
+
new Uint8Array(encodeMessage(MessageKind.TransportProtocol, t)),
|
|
198
|
+
);
|
|
199
|
+
const out: number[] = [];
|
|
200
|
+
for (const entry of entries) {
|
|
201
|
+
let len = entry.length;
|
|
202
|
+
do {
|
|
203
|
+
let b = len & 0x7f;
|
|
204
|
+
len >>>= 7;
|
|
205
|
+
if (len !== 0) b |= 0x80;
|
|
206
|
+
out.push(b);
|
|
207
|
+
} while (len !== 0);
|
|
208
|
+
out.push(...entry);
|
|
209
|
+
}
|
|
210
|
+
return new Uint8Array(out);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Reads the framing `encodeTransportList` writes. Order is the peer's and is
|
|
215
|
+
* preserved exactly — the library filters a peer's endpoints but never ranks
|
|
216
|
+
* them, so this order is the peer's own preference, not a recommendation.
|
|
217
|
+
*/
|
|
218
|
+
function decodeTransportList(framed: Uint8Array | ArrayBuffer): TransportProtocol[] {
|
|
219
|
+
const buf = framed instanceof Uint8Array ? framed : new Uint8Array(framed);
|
|
220
|
+
const out: TransportProtocol[] = [];
|
|
221
|
+
let i = 0;
|
|
222
|
+
while (i < buf.length) {
|
|
223
|
+
let len = 0;
|
|
224
|
+
let shift = 0;
|
|
225
|
+
for (;;) {
|
|
226
|
+
if (i >= buf.length) {
|
|
227
|
+
throw new Error('truncated transport list: length prefix runs past the end');
|
|
228
|
+
}
|
|
229
|
+
const b = buf[i++]!;
|
|
230
|
+
len |= (b & 0x7f) << shift;
|
|
231
|
+
if ((b & 0x80) === 0) break;
|
|
232
|
+
shift += 7;
|
|
233
|
+
}
|
|
234
|
+
if (i + len > buf.length) {
|
|
235
|
+
throw new Error('truncated transport list: entry runs past the end');
|
|
236
|
+
}
|
|
237
|
+
out.push(
|
|
238
|
+
decodeMessage<TransportProtocol>(
|
|
239
|
+
MessageKind.TransportProtocol,
|
|
240
|
+
buf.subarray(i, i + len),
|
|
241
|
+
),
|
|
242
|
+
);
|
|
243
|
+
i += len;
|
|
244
|
+
}
|
|
245
|
+
return out;
|
|
246
|
+
}
|
|
247
|
+
|
|
191
248
|
const pairing = {
|
|
192
249
|
request: {
|
|
193
250
|
create_contact(
|
|
194
251
|
channel_id: bigint,
|
|
195
252
|
contact_mode: ContactMode | number,
|
|
196
|
-
|
|
253
|
+
transport_protocols: TransportProtocol[],
|
|
197
254
|
): CreateContactResult {
|
|
198
255
|
// The C entry point also accepts a caller-supplied nonce behind a
|
|
199
256
|
// presence flag. `@derec-alliance/nodejs` has no such parameter, so the
|
|
@@ -203,7 +260,7 @@ const pairing = {
|
|
|
203
260
|
'create_contact_message',
|
|
204
261
|
channel_id,
|
|
205
262
|
contact_mode,
|
|
206
|
-
|
|
263
|
+
encodeTransportList(transport_protocols),
|
|
207
264
|
0,
|
|
208
265
|
0n,
|
|
209
266
|
) as { contact_wire_bytes: ArrayBuffer; secret_key_material: ArrayBuffer };
|
|
@@ -223,7 +280,7 @@ const pairing = {
|
|
|
223
280
|
|
|
224
281
|
produce(
|
|
225
282
|
kind: SenderKind,
|
|
226
|
-
|
|
283
|
+
transport_protocols: TransportProtocol[],
|
|
227
284
|
contact_message: ContactMessage,
|
|
228
285
|
communication_info: CommunicationInfo | null,
|
|
229
286
|
parameter_range: ParameterRange | null,
|
|
@@ -231,7 +288,7 @@ const pairing = {
|
|
|
231
288
|
const result = call(
|
|
232
289
|
'produce_pair_request_message',
|
|
233
290
|
kind,
|
|
234
|
-
|
|
291
|
+
encodeTransportList(transport_protocols),
|
|
235
292
|
encodeContact(contact_message),
|
|
236
293
|
encodeOptionalMessage(MessageKind.CommunicationInfo, communication_info),
|
|
237
294
|
encodeOptionalMessage(MessageKind.ParameterRange, parameter_range),
|
|
@@ -262,12 +319,12 @@ const pairing = {
|
|
|
262
319
|
},
|
|
263
320
|
|
|
264
321
|
produce_pre_pair(
|
|
265
|
-
|
|
322
|
+
own_transports: TransportProtocol[],
|
|
266
323
|
contact_message: ContactMessage,
|
|
267
324
|
): ProducePrePairResult {
|
|
268
325
|
const envelope = call(
|
|
269
326
|
'produce_pre_pair_request_message',
|
|
270
|
-
|
|
327
|
+
encodeTransportList(own_transports),
|
|
271
328
|
encodeContact(contact_message),
|
|
272
329
|
);
|
|
273
330
|
return { envelope: bytes(envelope) };
|
|
@@ -293,6 +350,7 @@ const pairing = {
|
|
|
293
350
|
secret_key: Uint8Array,
|
|
294
351
|
communication_info: CommunicationInfo | null,
|
|
295
352
|
parameter_range: ParameterRange | null,
|
|
353
|
+
unsafe_connection = false,
|
|
296
354
|
): PairingResponseProduceResult {
|
|
297
355
|
const result = call(
|
|
298
356
|
'produce_pair_response_message',
|
|
@@ -301,18 +359,16 @@ const pairing = {
|
|
|
301
359
|
secret_key,
|
|
302
360
|
encodeOptionalMessage(MessageKind.CommunicationInfo, communication_info),
|
|
303
361
|
encodeOptionalMessage(MessageKind.ParameterRange, parameter_range),
|
|
362
|
+
unsafe_connection,
|
|
304
363
|
) as {
|
|
305
364
|
response_wire_bytes: ArrayBuffer;
|
|
306
|
-
|
|
365
|
+
peer_transports: ArrayBuffer;
|
|
307
366
|
shared_key: ArrayBuffer;
|
|
308
367
|
channel_id: bigint;
|
|
309
368
|
};
|
|
310
369
|
return {
|
|
311
370
|
envelope: bytes(result.response_wire_bytes),
|
|
312
|
-
|
|
313
|
-
MessageKind.TransportProtocol,
|
|
314
|
-
result.peer_transport_protocol,
|
|
315
|
-
),
|
|
371
|
+
peer_transports: decodeTransportList(result.peer_transports),
|
|
316
372
|
shared_key: bytes(result.shared_key),
|
|
317
373
|
channel_id: result.channel_id,
|
|
318
374
|
};
|
|
@@ -402,7 +458,7 @@ const recovery = {
|
|
|
402
458
|
secret_id: bigint,
|
|
403
459
|
version: number,
|
|
404
460
|
shared_key: Uint8Array,
|
|
405
|
-
reply_to?: TransportProtocol
|
|
461
|
+
reply_to?: TransportProtocol[],
|
|
406
462
|
): ProduceResult {
|
|
407
463
|
const envelope = call(
|
|
408
464
|
'produce_get_share_request_message',
|
|
@@ -505,7 +561,7 @@ const sharing = {
|
|
|
505
561
|
keep_list: number[],
|
|
506
562
|
description: string,
|
|
507
563
|
shared_key: Uint8Array,
|
|
508
|
-
reply_to?: TransportProtocol
|
|
564
|
+
reply_to?: TransportProtocol[],
|
|
509
565
|
): ProduceResult {
|
|
510
566
|
const envelope = call(
|
|
511
567
|
'produce_store_share_request_message',
|
|
@@ -596,7 +652,7 @@ const unpairing = {
|
|
|
596
652
|
channel_id: bigint,
|
|
597
653
|
memo: string,
|
|
598
654
|
shared_key: Uint8Array,
|
|
599
|
-
reply_to?: TransportProtocol
|
|
655
|
+
reply_to?: TransportProtocol[],
|
|
600
656
|
): ProduceResult {
|
|
601
657
|
const envelope = call(
|
|
602
658
|
'produce_unpair_request_message',
|
|
@@ -668,7 +724,7 @@ const verification = {
|
|
|
668
724
|
secret_id: bigint,
|
|
669
725
|
version: number,
|
|
670
726
|
shared_key: Uint8Array,
|
|
671
|
-
reply_to?: TransportProtocol
|
|
727
|
+
reply_to?: TransportProtocol[],
|
|
672
728
|
): ProduceResult {
|
|
673
729
|
const envelope = call(
|
|
674
730
|
'produce_verify_share_request_message',
|
package/src/protocol.ts
CHANGED
|
@@ -13,13 +13,14 @@ import type {
|
|
|
13
13
|
DeRecEvent,
|
|
14
14
|
DiscoveryParams,
|
|
15
15
|
PairingParams,
|
|
16
|
+
ParameterRange,
|
|
16
17
|
ProtectSecretParams,
|
|
17
18
|
RecoverSecretParams,
|
|
18
|
-
|
|
19
|
+
UnpairReplicaParams,
|
|
19
20
|
SecretStore,
|
|
20
21
|
ShareStore,
|
|
21
22
|
StateStore,
|
|
22
|
-
|
|
23
|
+
ReplicaDiscoveryParams,
|
|
23
24
|
Target,
|
|
24
25
|
Timeouts,
|
|
25
26
|
Transport,
|
|
@@ -86,12 +87,14 @@ function decodeEvents(buffer: ArrayBuffer): DeRecEvent[] {
|
|
|
86
87
|
* against does not carry this enum (it
|
|
87
88
|
* only covers the Rust-internal serde enums listed under its `"enums"` key);
|
|
88
89
|
* the transport `Protocol` enum lives in `protobufs/transportprotocol.proto`
|
|
89
|
-
* instead, where
|
|
90
|
+
* instead, where `HTTPS = 0` and `GRPC = 1` are defined.
|
|
90
91
|
*/
|
|
91
92
|
export function protocolDiscriminant(protocol: string): number {
|
|
92
93
|
switch (protocol.toLowerCase()) {
|
|
93
94
|
case 'https':
|
|
94
95
|
return 0;
|
|
96
|
+
case 'grpc':
|
|
97
|
+
return 1;
|
|
95
98
|
default:
|
|
96
99
|
throw new Error(`DeRec: unknown transport protocol "${protocol}"`);
|
|
97
100
|
}
|
|
@@ -156,7 +159,7 @@ export function buildRestoreParams(
|
|
|
156
159
|
helpers: recoveredSecret.helpers.map((helper) => {
|
|
157
160
|
const out: Record<string, unknown> = {
|
|
158
161
|
channel_id: helper.channel_id,
|
|
159
|
-
|
|
162
|
+
transports: helper.transports,
|
|
160
163
|
shared_key: Array.from(helper.shared_key),
|
|
161
164
|
};
|
|
162
165
|
const info = communicationInfoOrOmit(helper.communication_info);
|
|
@@ -177,7 +180,7 @@ export function buildRestoreParams(
|
|
|
177
180
|
members: recoveredSecret.replicas.members.map((member) => {
|
|
178
181
|
const out: Record<string, unknown> = {
|
|
179
182
|
replica_id: member.replica_id,
|
|
180
|
-
|
|
183
|
+
transports: member.transports,
|
|
181
184
|
role: member.role,
|
|
182
185
|
};
|
|
183
186
|
const info = communicationInfoOrOmit(member.communication_info);
|
|
@@ -258,17 +261,22 @@ function buildStartParams(flowKind: FlowKind, params: unknown): Uint8Array {
|
|
|
258
261
|
if (p.communication_info !== undefined) {
|
|
259
262
|
out.communication_info = p.communication_info;
|
|
260
263
|
}
|
|
261
|
-
if (p.
|
|
264
|
+
if (p.own_transports !== undefined && p.own_transports.length > 0) {
|
|
265
|
+
out.own_transports = p.own_transports;
|
|
266
|
+
// The first entry also fills the deprecated singular field so a peer
|
|
267
|
+
// predating `supported_transports` still learns the new address.
|
|
268
|
+
out.transport_protocol = p.own_transports[0];
|
|
269
|
+
} else if (p.transport_protocol !== undefined) {
|
|
262
270
|
out.transport_protocol = p.transport_protocol;
|
|
263
271
|
}
|
|
264
272
|
return jsonToBytes(out);
|
|
265
273
|
}
|
|
266
|
-
case FlowKind.
|
|
274
|
+
case FlowKind.ReplicaDiscovery:
|
|
267
275
|
// No parameters: the group and this device's own version both come
|
|
268
276
|
// from the stores.
|
|
269
277
|
return jsonToBytes({});
|
|
270
|
-
case FlowKind.
|
|
271
|
-
const p = params as
|
|
278
|
+
case FlowKind.UnpairReplica: {
|
|
279
|
+
const p = params as UnpairReplicaParams;
|
|
272
280
|
const out: Record<string, unknown> = { replica_id: p.replica_id };
|
|
273
281
|
if (p.memo !== undefined) {
|
|
274
282
|
out.memo = p.memo;
|
|
@@ -341,12 +349,43 @@ export class DeRecProtocolBuilder {
|
|
|
341
349
|
return this;
|
|
342
350
|
}
|
|
343
351
|
|
|
352
|
+
/**
|
|
353
|
+
* @deprecated Use {@link withOwnTransports}, which takes the whole
|
|
354
|
+
* preference list — `withOwnTransports([endpoint])` is the direct
|
|
355
|
+
* replacement. Removed at 0.0.5.
|
|
356
|
+
*/
|
|
344
357
|
withOwnTransport(endpoint: { uri: string; protocol: string }): this {
|
|
345
358
|
this.config.own_transport_uri = endpoint.uri;
|
|
346
359
|
this.config.own_transport_protocol = protocolDiscriminant(endpoint.protocol);
|
|
347
360
|
return this;
|
|
348
361
|
}
|
|
349
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Set every transport endpoint this application serves, in preference
|
|
365
|
+
* order. Written to the config's `own_transports` array, which takes
|
|
366
|
+
* precedence over `own_transport_uri` / `own_transport_protocol` on the
|
|
367
|
+
* Rust side when non-empty — see `ProtocolConfig` in
|
|
368
|
+
* `library/src/interop/ffi/protocol/handle/mod.rs`.
|
|
369
|
+
*
|
|
370
|
+
* The order given is forwarded verbatim: it is not sorted, deduplicated,
|
|
371
|
+
* or reordered here. It is this application's own preference and
|
|
372
|
+
* decides which of a peer's offered endpoints is used. Every listed
|
|
373
|
+
* transport must actually be served, because delivery is push-only —
|
|
374
|
+
* listing an endpoint this application does not serve makes pairing
|
|
375
|
+
* succeed and replies vanish.
|
|
376
|
+
*
|
|
377
|
+
* Supersedes {@link withOwnTransport} for applications serving more
|
|
378
|
+
* than one transport; the single-endpoint setter remains fully
|
|
379
|
+
* supported.
|
|
380
|
+
*/
|
|
381
|
+
withOwnTransports(transports: { uri: string; protocol: string }[]): this {
|
|
382
|
+
this.config.own_transports = transports.map((t) => ({
|
|
383
|
+
uri: t.uri,
|
|
384
|
+
protocol: protocolDiscriminant(t.protocol),
|
|
385
|
+
}));
|
|
386
|
+
return this;
|
|
387
|
+
}
|
|
388
|
+
|
|
350
389
|
/** Default: 3. */
|
|
351
390
|
withThreshold(threshold: number): this {
|
|
352
391
|
this.config.threshold = threshold;
|
|
@@ -371,12 +410,30 @@ export class DeRecProtocolBuilder {
|
|
|
371
410
|
return this;
|
|
372
411
|
}
|
|
373
412
|
|
|
374
|
-
/**
|
|
413
|
+
/**
|
|
414
|
+
* @deprecated Use {@link withUnsafeConnection}, which names both gated
|
|
415
|
+
* schemes. Removed at 0.0.5. Default: false.
|
|
416
|
+
*/
|
|
375
417
|
withUnsafeHttp(allow: boolean): this {
|
|
376
418
|
this.config.unsafe_http = allow;
|
|
377
419
|
return this;
|
|
378
420
|
}
|
|
379
421
|
|
|
422
|
+
/**
|
|
423
|
+
* Accept plaintext `http://` and `grpc://` transport endpoints.
|
|
424
|
+
* **Development only.** Default: false. Supersedes
|
|
425
|
+
* {@link withUnsafeHttp}, which names only the HTTP scheme.
|
|
426
|
+
*
|
|
427
|
+
* Either flag alone is honored. Setting both to disagreeing values fails
|
|
428
|
+
* construction with the error code `CONFLICTING_PLAINTEXT_OPT_IN` rather
|
|
429
|
+
* than resolving silently, because precedence would hand the decision to
|
|
430
|
+
* the flag being removed.
|
|
431
|
+
*/
|
|
432
|
+
withUnsafeConnection(allow: boolean): this {
|
|
433
|
+
this.config.unsafe_connection = allow;
|
|
434
|
+
return this;
|
|
435
|
+
}
|
|
436
|
+
|
|
380
437
|
/**
|
|
381
438
|
* Default: empty. `derec_protocol_new`'s own `communication_info` argument
|
|
382
439
|
* is a pre-encoded `CommunicationInfo` protobuf message, and this SDK has
|
|
@@ -444,6 +501,41 @@ export class DeRecProtocolBuilder {
|
|
|
444
501
|
return this;
|
|
445
502
|
}
|
|
446
503
|
|
|
504
|
+
/**
|
|
505
|
+
* Declare the bounds this node advertises during pair negotiation.
|
|
506
|
+
*
|
|
507
|
+
* Embedded in outbound `PairRequest`/`PairResponse` envelopes and checked
|
|
508
|
+
* against the peer's range on inbound ones: a range that fails to
|
|
509
|
+
* intersect rejects the pairing. Every bound is optional and defaults to
|
|
510
|
+
* `0`, which the protocol reads as "no constraint on this dimension".
|
|
511
|
+
*
|
|
512
|
+
* Default: unset — no constraints advertised, every peer range accepted.
|
|
513
|
+
*/
|
|
514
|
+
withParameterRange(range: Partial<ParameterRange>): this {
|
|
515
|
+
const n = (v: bigint | undefined) => Number(v ?? 0n);
|
|
516
|
+
this.config.parameter_range = {
|
|
517
|
+
min_share_size: n(range.min_share_size),
|
|
518
|
+
max_share_size: n(range.max_share_size),
|
|
519
|
+
min_time_between_verifications: n(range.min_time_between_verifications),
|
|
520
|
+
max_time_between_verifications: n(range.max_time_between_verifications),
|
|
521
|
+
min_time_between_share_updates: n(range.min_time_between_share_updates),
|
|
522
|
+
max_time_between_share_updates: n(range.max_time_between_share_updates),
|
|
523
|
+
min_unresponsive_deletion_timeout: n(
|
|
524
|
+
range.min_unresponsive_deletion_timeout,
|
|
525
|
+
),
|
|
526
|
+
max_unresponsive_deletion_timeout: n(
|
|
527
|
+
range.max_unresponsive_deletion_timeout,
|
|
528
|
+
),
|
|
529
|
+
min_unresponsive_deactivation_timeout: n(
|
|
530
|
+
range.min_unresponsive_deactivation_timeout,
|
|
531
|
+
),
|
|
532
|
+
max_unresponsive_deactivation_timeout: n(
|
|
533
|
+
range.max_unresponsive_deactivation_timeout,
|
|
534
|
+
),
|
|
535
|
+
};
|
|
536
|
+
return this;
|
|
537
|
+
}
|
|
538
|
+
|
|
447
539
|
build(): DeRecProtocol {
|
|
448
540
|
const config = {
|
|
449
541
|
secret_id: this.secretIdValue.toString(),
|
|
@@ -526,7 +618,19 @@ export class DeRecProtocol {
|
|
|
526
618
|
return this.host.setCommunicationInfo(jsonToBytes(info)) as Promise<void>;
|
|
527
619
|
}
|
|
528
620
|
|
|
529
|
-
/**
|
|
621
|
+
/**
|
|
622
|
+
* Replace this node's endpoint for one protocol, leaving the others
|
|
623
|
+
* alone. A node serves at most one endpoint per protocol, so the
|
|
624
|
+
* `(uri, protocol)` pair identifies the entry it replaces; an entry for a
|
|
625
|
+
* protocol not yet served is appended, and a replaced one keeps its
|
|
626
|
+
* position in the preference order.
|
|
627
|
+
*
|
|
628
|
+
* Returns a `Promise` for the same reason {@link setCommunicationInfo} does.
|
|
629
|
+
*
|
|
630
|
+
* @deprecated Use {@link setOwnTransports}, which takes the whole
|
|
631
|
+
* preference list and is the only way to change which protocols this node
|
|
632
|
+
* serves, or their order. Removed at 0.0.5.
|
|
633
|
+
*/
|
|
530
634
|
setOwnTransport(uri: string, protocol: string): Promise<void> {
|
|
531
635
|
return this.host.setOwnTransport(
|
|
532
636
|
uri,
|
|
@@ -534,6 +638,27 @@ export class DeRecProtocol {
|
|
|
534
638
|
) as Promise<void>;
|
|
535
639
|
}
|
|
536
640
|
|
|
641
|
+
/**
|
|
642
|
+
* Replaces every endpoint this node advertises, in preference order —
|
|
643
|
+
* the runtime counterpart to `withOwnTransports`, and the only way to
|
|
644
|
+
* change a multi-endpoint node's set ({@link setOwnTransport} collapses
|
|
645
|
+
* it to the one endpoint it is given).
|
|
646
|
+
*
|
|
647
|
+
* Every entry is validated before any is stored, so a malformed URI
|
|
648
|
+
* leaves the previous set intact. An empty array is rejected.
|
|
649
|
+
*
|
|
650
|
+
* Returns a `Promise` for the same reason {@link setCommunicationInfo} does.
|
|
651
|
+
*/
|
|
652
|
+
setOwnTransports(
|
|
653
|
+
transports: { uri: string; protocol: string }[],
|
|
654
|
+
): Promise<void> {
|
|
655
|
+
const wire = transports.map(({ uri, protocol }) => ({
|
|
656
|
+
uri,
|
|
657
|
+
protocol: protocolDiscriminant(protocol),
|
|
658
|
+
}));
|
|
659
|
+
return this.host.setOwnTransports(jsonToBytes(wire)) as Promise<void>;
|
|
660
|
+
}
|
|
661
|
+
|
|
537
662
|
/**
|
|
538
663
|
* Decodes the `contact_wire_bytes` `derec_protocol_create_contact`
|
|
539
664
|
* produces into a typed `ContactMessage`, so an application can read the
|
|
@@ -565,8 +690,8 @@ export class DeRecProtocol {
|
|
|
565
690
|
start(flowKind: FlowKind.RecoverSecret, params: RecoverSecretParams): Promise<DeRecEvent[]>;
|
|
566
691
|
start(flowKind: FlowKind.Unpair, params: UnpairParams): Promise<DeRecEvent[]>;
|
|
567
692
|
start(flowKind: FlowKind.UpdateChannelInfo, params: UpdateChannelInfoParams): Promise<DeRecEvent[]>;
|
|
568
|
-
start(flowKind: FlowKind.
|
|
569
|
-
start(flowKind: FlowKind.
|
|
693
|
+
start(flowKind: FlowKind.ReplicaDiscovery, params?: ReplicaDiscoveryParams): Promise<DeRecEvent[]>;
|
|
694
|
+
start(flowKind: FlowKind.UnpairReplica, params: UnpairReplicaParams): Promise<DeRecEvent[]>;
|
|
570
695
|
async start(flowKind: FlowKind, params?: unknown): Promise<DeRecEvent[]> {
|
|
571
696
|
const paramsBytes = buildStartParams(flowKind, params);
|
|
572
697
|
const buffer = (await this.host.start(flowKind, paramsBytes)) as ArrayBuffer;
|