Skip to content

feat: tc token - #280

Merged
jlucaso1 merged 2 commits into
mainfrom
feat-tc-token
Feb 13, 2026
Merged

feat: tc token#280
jlucaso1 merged 2 commits into
mainfrom
feat-tc-token

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Feb 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Trusted contact privacy tokens added to enhance 1:1 messaging security.
    • Tokens are automatically included in profile picture requests and direct messages.
    • Incoming privacy-token notifications are processed and persisted locally.
    • Automatic pruning removes expired tokens from local storage.
    • Presence subscription flows can include privacy tokens.
    • Public TcToken client API to issue, fetch, list and prune tokens.

@coderabbitai

coderabbitai Bot commented Feb 13, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds Trusted Contact (TC) privacy token support across the codebase: IQ spec and parsing, storage schema and SQLite implementation, client API (TcToken handle), message/profile/presence integration, notification handling, and background pruning.

Changes

Cohort / File(s) Summary
Storage Traits & Types
wacore/src/store/traits.rs
Adds TcTokenEntry and five ProtocolStore/AppSyncStore methods: get_tc_token, put_tc_token, delete_tc_token, get_all_tc_token_jids, delete_expired_tc_tokens.
SQLite Schema & Migrations
storages/sqlite-storage/migrations/.../up.sql, .../down.sql, storages/sqlite-storage/src/schema.rs
Creates tc_tokens table and index; exposes table in Diesel schema and provides down migration.
SQLite Implementation & Tests
storages/sqlite-storage/src/sqlite_store.rs
Implements TC token CRUD, upsert, expiration deletion, and comprehensive unit tests for token lifecycle.
App Sync Mock Backend (tests)
src/appstate_sync.rs
Adds stub implementations of the five TC token methods for MockBackend with test-friendly defaults.
Client API & TcToken Feature
src/features/tctoken.rs, src/features/mod.rs, src/lib.rs, src/client.rs
Introduces TcToken handle on Client (tc_token()), methods: issue_tokens, prune_expired, get, get_all_jids; background pruning on connect. Re-exports TcToken.
IQ Spec & Utilities
wacore/src/iq/tctoken.rs, wacore/src/iq/mod.rs
New tctoken IQ module: constants, bucketing/expiration logic, time helpers, IssuePrivacyTokensSpec/response, parsers, build helpers, and tests.
Profile Picture IQ Integration
wacore/src/iq/contacts.rs, src/features/contacts.rs
Adds optional tc_token to ProfilePictureSpec with with_tc_token; contacts flow fetches and applies TC token for non-group JIDs.
Outgoing Message Integration
src/send.rs
Adds maybe_include_tc_token, lookup_tc_token_for_jid, and LID resolution to attach or issue TC tokens for 1:1 messages.
Presence Subscription
src/features/presence.rs
Adds Presence::subscribe which optionally injects <tctoken> into presence subscribe stanzas.
Notification Handling
src/handlers/notification.rs
Adds privacy_token notification dispatch and handler that parses tokens, resolves sender LID, and updates stored TcTokenEntry with monotonic timestamp logic.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Client
    participant IQ
    participant Server
    participant Store

    User->>Client: tc_token().issue_tokens([jid])
    Client->>IQ: build IssuePrivacyTokensSpec
    IQ->>Server: send IQ set (issue tokens)
    Server-->>IQ: response with ReceivedTcToken(s)
    IQ-->>Client: parsed tokens
    Client->>Store: put_tc_token(jid, TcTokenEntry)
    Store-->>Client: Ok
    Client-->>User: return ReceivedTcToken(s)

    rect rgb(100, 150, 200, 0.5)
    Note over Client,Store: Background pruning
    Client->>Store: delete_expired_tc_tokens(cutoff)
    Store-->>Client: deleted_count
    end
Loading
sequenceDiagram
    participant Sender
    participant MessageHandler
    participant Client
    participant Store
    participant Server

    Sender->>MessageHandler: send 1:1 message to jid
    MessageHandler->>Client: lookup_tc_token_for_jid(jid)
    Client->>Store: get_tc_token(jid)
    Store-->>Client: Option<TcTokenEntry>

    alt token valid
        Client-->>MessageHandler: Some(token)
        MessageHandler->>MessageHandler: attach <tctoken> to stanza
    else token missing/expired
        MessageHandler->>Client: tc_token().issue_tokens([jid])
        Client->>Server: IQ set issue tokens
        Server-->>Client: ReceivedTcToken
        Client->>Store: put_tc_token(jid, TcTokenEntry)
        Client-->>MessageHandler: token
        MessageHandler->>MessageHandler: attach <tctoken> to stanza
    end

    MessageHandler->>Server: send message (with optional <tctoken>)
    Server-->>MessageHandler: ack
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I nibble code in twilight's glow,
Tokens tucked where whispers flow,
Buckets roll and stanzas sing,
Stored with care, a trusting spring,
Hoppity-hop—privacy on the go!

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'feat: tc token' is extremely vague and does not meaningfully describe the changeset. While it mentions 'tc token', it lacks specificity about the feature's scope or purpose. Use a more descriptive title that clarifies the primary change, such as 'feat: add TC token privacy system for 1:1 messaging' or 'feat: implement trusted contact privacy token management'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-tc-token

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/send.rs (2)

449-455: Comment slightly misleading — own JID skip happens inside maybe_include_tc_token.

The comment says "Skip for newsletters, groups, and own JID" but the if only checks groups/newsletters. The own-JID check is correctly implemented inside maybe_include_tc_token (line 505-517), so behavior is correct, but the comment here could confuse future readers.


601-625: Minor DRY observation: LID resolution logic duplicated.

The JID-to-token-key resolution pattern (lines 607-613) is identical to lines 520-527 in maybe_include_tc_token. Consider extracting a small helper like fn resolve_token_jid(&self, jid: &Jid) -> String to share this logic.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Feb 13, 2026

Copy link
Copy Markdown

🐰 Bencher Report

Branchfeat-tc-token
Testbedubuntu-latest

🚨 1 Alert

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Upper Boundary
(Limit %)
binary_benchmark::unpack_group::bench_unpack_compressedInstructions
instructions x 1e3
📈 plot
🚷 threshold
🚨 alert (🔔)
555.99 x 1e3
(+7.44%)Baseline: 517.48 x 1e3
543.35 x 1e3
(102.33%)

Click to view all benchmark results
BenchmarkInstructionsBenchmark Result
instructions
(Result Δ%)
Upper Boundary
instructions
(Limit %)
binary_benchmark::attr_parser_group::bench_attr_parser attr_lookup:setup_attr_marshaled()📈 view plot
🚷 view threshold
6,124.00
(-15.08%)Baseline: 7,211.87
7,572.46
(80.87%)
binary_benchmark::child_iteration_group::bench_get_children_by_tag📈 view plot
🚷 view threshold
850,819.00
(+0.01%)Baseline: 850,747.31
893,284.68
(95.25%)
binary_benchmark::jid_optimization_group::bench_jid_to_owned_access jid_access:setup_jid_heavy_marshaled()📈 view plot
🚷 view threshold
22,212.00
(-10.03%)Baseline: 24,687.16
25,921.52
(85.69%)
binary_benchmark::marshal_group::bench_marshal_allocating📈 view plot
🚷 view threshold
119,220.00
(-12.33%)Baseline: 135,980.69
142,779.72
(83.50%)
binary_benchmark::marshal_group::bench_marshal_auto_allocating📈 view plot
🚷 view threshold
119,248.00
(0.00%)Baseline: 119,248.00
125,210.40
(95.24%)
binary_benchmark::marshal_group::bench_marshal_auto_huge_bytes_allocating📈 view plot
🚷 view threshold
534,027.00
(0.00%)Baseline: 534,027.00
560,728.35
(95.24%)
binary_benchmark::marshal_group::bench_marshal_auto_long_string📈 view plot
🚷 view threshold
17,350.00
(0.00%)Baseline: 17,350.00
18,217.50
(95.24%)
binary_benchmark::marshal_group::bench_marshal_auto_many_children_allocating📈 view plot
🚷 view threshold
17,136,927.00
(0.00%)Baseline: 17,136,927.00
17,993,773.35
(95.24%)
binary_benchmark::marshal_group::bench_marshal_exact_allocating📈 view plot
🚷 view threshold
176,721.00
(0.00%)Baseline: 176,721.00
185,557.05
(95.24%)
binary_benchmark::marshal_group::bench_marshal_exact_huge_bytes_allocating📈 view plot
🚷 view threshold
535,440.00
(0.00%)Baseline: 535,440.00
562,212.00
(95.24%)
binary_benchmark::marshal_group::bench_marshal_exact_long_string📈 view plot
🚷 view threshold
19,404.00
(0.00%)Baseline: 19,404.00
20,374.20
(95.24%)
binary_benchmark::marshal_group::bench_marshal_exact_many_children_allocating📈 view plot
🚷 view threshold
42,772,453.00
(0.00%)Baseline: 42,772,453.00
44,911,075.65
(95.24%)
binary_benchmark::marshal_group::bench_marshal_huge_bytes_allocating📈 view plot
🚷 view threshold
534,466.00
(0.00%)Baseline: 534,466.00
561,189.30
(95.24%)
binary_benchmark::marshal_group::bench_marshal_long_string📈 view plot
🚷 view threshold
17,323.00
(-10.82%)Baseline: 19,424.71
20,395.95
(84.93%)
binary_benchmark::marshal_group::bench_marshal_many_children_allocating📈 view plot
🚷 view threshold
17,137,747.00
(0.00%)Baseline: 17,137,747.00
17,994,634.35
(95.24%)
binary_benchmark::marshal_group::bench_marshal_reusing_buffer📈 view plot
🚷 view threshold
129,121.00
(-5.26%)Baseline: 136,291.99
143,106.59
(90.23%)
binary_benchmark::marshal_group::bench_marshal_reusing_buffer_vec_writer📈 view plot
🚷 view threshold
119,320.00
(0.00%)Baseline: 119,320.00
125,286.00
(95.24%)
binary_benchmark::roundtrip_group::bench_roundtrip large:setup_large_marshaled()📈 view plot
🚷 view threshold
93,707.00
(-11.50%)Baseline: 105,887.80
111,182.19
(84.28%)
binary_benchmark::roundtrip_group::bench_roundtrip small:setup_small_marshaled()📈 view plot
🚷 view threshold
7,249.00
(-14.19%)Baseline: 8,447.33
8,869.70
(81.73%)
binary_benchmark::roundtrip_group::bench_roundtrip_auto large:setup_large_marshaled()📈 view plot
🚷 view threshold
93,738.00
(0.00%)Baseline: 93,738.00
98,424.90
(95.24%)
binary_benchmark::roundtrip_group::bench_roundtrip_auto small:setup_small_marshaled()📈 view plot
🚷 view threshold
7,272.00
(0.00%)Baseline: 7,272.00
7,635.60
(95.24%)
binary_benchmark::roundtrip_group::bench_roundtrip_exact large:setup_large_marshaled()📈 view plot
🚷 view threshold
109,523.00
(0.00%)Baseline: 109,523.00
114,999.15
(95.24%)
binary_benchmark::roundtrip_group::bench_roundtrip_exact small:setup_small_marshaled()📈 view plot
🚷 view threshold
8,784.00
(0.00%)Baseline: 8,784.00
9,223.20
(95.24%)
binary_benchmark::unmarshal_group::bench_unmarshal large:setup_large_marshaled()📈 view plot
🚷 view threshold
44,794.00
(-9.19%)Baseline: 49,325.49
51,791.77
(86.49%)
binary_benchmark::unmarshal_group::bench_unmarshal small:setup_small_marshaled()📈 view plot
🚷 view threshold
2,588.00
(-17.14%)Baseline: 3,123.46
3,279.64
(78.91%)
binary_benchmark::unpack_group::bench_unpack_compressed📈 view plot
🚷 view threshold
🚨 view alert (🔔)
555,986.00
(+7.44%)Baseline: 517,476.96
543,350.80
(102.33%)

binary_benchmark::unpack_group::bench_unpack_uncompressed📈 view plot
🚷 view threshold
771.00
(-0.86%)Baseline: 777.72
816.61
(94.42%)
libsignal_benchmark::conversation_group::bench_full_dm_conversation full:setup_conversation_data()📈 view plot
🚷 view threshold
27,601,503.00
(-0.55%)Baseline: 27,755,462.03
29,143,235.13
(94.71%)
libsignal_benchmark::dm_group::bench_dm_decrypt_first_message decrypt_prekey:setup_dm_with_first_message()📈 view plot
🚷 view threshold
5,540,334.00
(-0.42%)Baseline: 5,563,668.87
5,841,852.31
(94.84%)
libsignal_benchmark::dm_group::bench_dm_encrypt_first_message first_msg:setup_dm_session()📈 view plot
🚷 view threshold
178,106.00
(+0.08%)Baseline: 177,970.21
186,868.72
(95.31%)
libsignal_benchmark::dm_group::bench_dm_encrypt_subsequent_message subsequent:setup_established_dm_session()📈 view plot
🚷 view threshold
178,917.00
(+0.08%)Baseline: 178,782.02
187,721.12
(95.31%)
libsignal_benchmark::dm_group::bench_dm_session_establishment setup:setup_dm_users()📈 view plot
🚷 view threshold
17,415,479.00
(+0.74%)Baseline: 17,287,604.97
18,151,985.22
(95.94%)
libsignal_benchmark::group_messaging_group::bench_group_create_distribution_message create:setup_group_sender()📈 view plot
🚷 view threshold
295,894.00
(+0.03%)Baseline: 295,802.77
310,592.91
(95.27%)
libsignal_benchmark::group_messaging_group::bench_group_decrypt_message decrypt:setup_group_with_encrypted_message()📈 view plot
🚷 view threshold
12,293,831.00
(-2.33%)Baseline: 12,586,894.65
13,216,239.38
(93.02%)
libsignal_benchmark::group_messaging_group::bench_group_encrypt_message encrypt:setup_group_with_distribution()📈 view plot
🚷 view threshold
715,619.00
(-0.03%)Baseline: 715,861.32
751,654.39
(95.21%)
libsignal_benchmark::session_optimization_group::bench_decrypt_with_previous_session previous_session:setup_with_archived_sessions()📈 view plot
🚷 view threshold
41,833.00
(+0.11%)Baseline: 41,788.37
43,877.79
(95.34%)
libsignal_benchmark::session_optimization_group::bench_message_key_eviction eviction:setup_message_key_eviction()📈 view plot
🚷 view threshold
15,561,842.00
(+0.00%)Baseline: 15,561,373.76
16,339,442.45
(95.24%)
libsignal_benchmark::session_optimization_group::bench_out_of_order_decryption out_of_order:setup_out_of_order_messages()📈 view plot
🚷 view threshold
5,504,889.00
(-0.34%)Baseline: 5,523,863.49
5,800,056.66
(94.91%)
libsignal_benchmark::session_optimization_group::bench_promote_matching_session promote:setup_promote_matching_session()📈 view plot
🚷 view threshold
956,786.00
(-0.68%)Baseline: 963,292.91
1,011,457.55
(94.59%)
libsignal_benchmark::signature_group::bench_key_generation keygen📈 view plot
🚷 view threshold
2,822,769.00
(-0.01%)Baseline: 2,823,188.41
2,964,347.83
(95.22%)
libsignal_benchmark::signature_group::bench_signature_creation sign:setup_keypair_with_message()📈 view plot
🚷 view threshold
3,444,364.00
(-3.29%)Baseline: 3,561,373.09
3,739,441.75
(92.11%)
libsignal_benchmark::signature_group::bench_signature_verification verify:setup_keypair_with_message()📈 view plot
🚷 view threshold
125,411,995.00
(-0.02%)Baseline: 125,434,148.14
131,705,855.54
(95.22%)
reporting_token_benchmark::content_extraction_group::bench_content_extraction extended:setup_extended_message()📈 view plot
🚷 view threshold
11,665.00
(-1.07%)Baseline: 11,790.69
12,380.22
(94.22%)
reporting_token_benchmark::content_extraction_group::bench_content_extraction simple:setup_simple_message()📈 view plot
🚷 view threshold
3,774.00
(-1.30%)Baseline: 3,823.63
4,014.82
(94.00%)
reporting_token_benchmark::full_generation_group::bench_full_token_generation extended:setup_full_gen_extended()📈 view plot
🚷 view threshold
87,777.00
(-0.23%)Baseline: 87,978.56
92,377.49
(95.02%)
reporting_token_benchmark::full_generation_group::bench_full_token_generation simple:setup_full_gen_simple()📈 view plot
🚷 view threshold
79,909.00
(-0.16%)Baseline: 80,034.51
84,036.23
(95.09%)
reporting_token_benchmark::key_derivation_group::bench_key_derivation📈 view plot
🚷 view threshold
51,010.00
(-0.04%)Baseline: 51,031.24
53,582.80
(95.20%)
reporting_token_benchmark::message_encoding_group::bench_message_encoding extended:setup_extended_message()📈 view plot
🚷 view threshold
5,749.00
(+0.25%)Baseline: 5,734.53
6,021.25
(95.48%)
reporting_token_benchmark::message_encoding_group::bench_message_encoding simple:setup_simple_message()📈 view plot
🚷 view threshold
2,109.00
(-0.30%)Baseline: 2,115.31
2,221.08
(94.95%)
reporting_token_benchmark::token_calculation_group::bench_token_calculation📈 view plot
🚷 view threshold
21,920.00
(+0.04%)Baseline: 21,911.49
23,007.07
(95.28%)
🐰 View full continuous benchmarking report in Bencher

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/handlers/notification.rs`:
- Around line 386-423: The code currently treats any non-Ok(Some(...)) result
from backend.get_tc_token(&sender_lid) as “no existing entry” and may overwrite
a newer token; change the control flow to match on
backend.get_tc_token(&sender_lid).await and handle three cases:
Ok(Some(existing)) — keep the existing monotonicity check and preserve
existing.sender_timestamp when updating; Ok(None) — create and store a new
TcTokenEntry with sender_timestamp=None as you already do; Err(e) — do NOT
create or overwrite the token, instead log a warning including the error (e) and
skip updating for sender_lid so monotonicity is preserved; reference
get_tc_token, put_tc_token, TcTokenEntry, sender_lid and received_tokens in your
changes.

In `@src/send.rs`:
- Around line 449-455: The code skips adding the tc_token for groups and
newsletters but the comment also says to skip for the client's own JID; update
the condition to include an "own JID" check before calling
self.maybe_include_tc_token(&to, &mut extra_stanza_nodes). Specifically, add a
comparison against the sender's JID (e.g., self.jid or the method/field that
holds the client's JID) so the if becomes something like: if !to.is_group() &&
!to.is_newsletter() && to != self.jid { ... } (use the exact symbol for the
client's JID in this module), then call maybe_include_tc_token as before;
alternatively adjust the comment if you intentionally want to include own JID.

In `@wacore/src/iq/tctoken.rs`:
- Around line 184-187: The code silently creates token_bytes = Vec::new() when
token_node.content isn't Some(NodeContent::Bytes(...)), which can lead to
constructing ReceivedTcToken with an empty token; instead, detect empty
token_bytes after the match and either skip creating/adding the ReceivedTcToken
or return an error, and emit a warning via your crate logger (e.g.,
tracing::warn! or the project's logger) so missing token content is visible;
update the logic around token_node/content handling and where ReceivedTcToken is
constructed to bail/continue when token_bytes.is_empty() and include a clear log
message referencing the token_node/ReceivedTcToken.
- Around line 173-182: Replace the optional_attr(...) + ok_or_else(...) usage
for mandatory attributes with required_attr to match the project's parsing
conventions: use required_attr(token_node, "jid") instead of
optional_attr(token_node, "jid").ok_or_else(...), and required_attr(token_node,
"t") instead of optional_attr(token_node, "t").ok_or_else(...); retain the
subsequent parsing steps and map_err error wrapping for jid.parse() and
t_str.parse() so only the attribute lookup changes (referencing token_node,
jid_str/t_str, and the parse map_err calls).
🧹 Nitpick comments (4)
wacore/src/iq/tctoken.rs (4)

61-100: Consider extracting the repeated now helper and accepting a clock parameter for testability.

The SystemTime::now()...as_secs() as i64 pattern is duplicated four times (lines 62–65, 81–84, 95–98, 125–128). Beyond the DRY concern, embedding wall-clock reads makes these functions non-deterministic — the test on line 296–303 already notes that boundary alignment makes assertions unreliable.

A lightweight improvement: extract a fn unix_now() -> i64 helper for deduplication, and consider accepting now: i64 as a parameter in the core logic functions (the public wrappers can still default to wall time). This lets tests exercise exact bucket boundaries deterministically.

♻️ Sketch
+fn unix_now() -> i64 {
+    std::time::SystemTime::now()
+        .duration_since(std::time::UNIX_EPOCH)
+        .unwrap_or_default()
+        .as_secs() as i64
+}
+
 pub fn is_tc_token_expired(token_timestamp: i64) -> bool {
-    let now = std::time::SystemTime::now()
-        .duration_since(std::time::UNIX_EPOCH)
-        .unwrap_or_default()
-        .as_secs() as i64;
-    now - token_timestamp >= TC_TOKEN_TOTAL_DURATION
+    is_tc_token_expired_at(token_timestamp, unix_now())
+}
+
+fn is_tc_token_expired_at(token_timestamp: i64, now: i64) -> bool {
+    now - token_timestamp >= TC_TOKEN_TOTAL_DURATION
 }

Same pattern for should_send_new_tc_token / tc_token_expiration_cutoff.


123-131: Constructor takes owned Vec<Jid> — consider taking &[Jid] per coding guidelines.

The guideline states constructors should accept references and clone internally. Taking Vec<Jid> forces callers to build an owned collection upfront.

♻️ Proposed fix
-    pub fn new(jids: Vec<Jid>) -> Self {
+    pub fn new(jids: &[Jid]) -> Self {
         let timestamp = std::time::SystemTime::now()
             .duration_since(std::time::UNIX_EPOCH)
             .unwrap_or_default()
             .as_secs() as i64;
-        Self { jids, timestamp }
+        Self { jids: jids.to_vec(), timestamp }
     }

As per coding guidelines, "IqSpec constructors should take &Jid instead of Jid to avoid forcing callers to clone; the clone happens inside the constructor."


231-238: Placeholder Jid::default() creates an incomplete struct — consider a safer representation.

Returning ReceivedTcToken with a default JID relies on every caller remembering to patch it. If someone forgets, the token silently carries an invalid/empty JID with no compile-time guard.

A safer alternative would be to return an intermediate type (e.g., a tuple of (Vec<u8>, i64) or a dedicated ParsedTokenData without the jid field) and let the caller construct ReceivedTcToken with the resolved JID. This makes the incomplete state unrepresentable.


289-304: Dead code in test: old_ts is computed but never asserted on.

old_ts is calculated (line 296) and then suppressed with let _ = old_ts; (line 303). Either remove it or add a meaningful assertion. As the comment notes, 1-bucket-back can be unreliable with wall time — this reinforces the earlier suggestion to accept now as a parameter for deterministic testing.

Comment thread src/handlers/notification.rs
Comment thread src/send.rs
Comment thread wacore/src/iq/tctoken.rs Outdated
Comment thread wacore/src/iq/tctoken.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant