Client styleguide changes

This commit is contained in:
Jazz Turner-Baggs 2025-08-15 09:26:02 -07:00
parent 3aa1d5e513
commit 86bb2e0930

View File

@ -6,7 +6,6 @@
import # Foreign import # Foreign
chronicles, chronicles,
chronos, chronos,
json,
std/sequtils, std/sequtils,
strformat, strformat,
strutils, strutils,
@ -32,7 +31,7 @@ logScope:
type KeyEntry* = object type KeyEntry* = object
keytype: string keyType: string
privateKey: PrivateKey privateKey: PrivateKey
timestamp: int64 timestamp: int64
@ -44,16 +43,17 @@ type
InboxV1Type, PrivateV1Type InboxV1Type, PrivateV1Type
ConvoWrapper* = object ConvoWrapper* = object
case convo_type*: ConvoType case convoType*: ConvoType
of InboxV1Type: of InboxV1Type:
inboxV1*: Inbox inboxV1*: Inbox
of PrivateV1Type: of PrivateV1Type:
privateV1*: PrivateV1 privateV1*: PrivateV1
type Client* = ref object type Client* = ref object
ident: Identity ident: Identity
ds*: WakuClient ds*: WakuClient
key_store: Table[string, KeyEntry] # Keyed by HexEncoded Public Key keyStore: Table[string, KeyEntry] # Keyed by HexEncoded Public Key
conversations: Table[string, ConvoWrapper] # Keyed by conversation ID conversations: Table[string, ConvoWrapper] # Keyed by conversation ID
inboundQueue: QueueRef inboundQueue: QueueRef
isRunning: bool isRunning: bool
@ -69,18 +69,18 @@ proc newClient*(name: string, cfg: WakuConfig): Client =
var q = QueueRef(queue: newAsyncQueue[ChatPayload](10)) var q = QueueRef(queue: newAsyncQueue[ChatPayload](10))
var c = Client(ident: createIdentity(name), var c = Client(ident: createIdentity(name),
ds: waku, ds: waku,
key_store: initTable[string, KeyEntry](), keyStore: initTable[string, KeyEntry](),
conversations: initTable[string, ConvoWrapper](), conversations: initTable[string, ConvoWrapper](),
inboundQueue: q, inboundQueue: q,
isRunning: false) isRunning: false)
let default_inbox = initInbox(c.ident.getAddr()) let defaultInbox = initInbox(c.ident.getAddr())
c.conversations[conversation_id_for(c.ident.getPubkey( c.conversations[conversationIdFor(c.ident.getPubkey(
))] = ConvoWrapper(convo_type: InboxV1Type, inboxV1: default_inbox) ))] = ConvoWrapper(convoType: InboxV1Type, inboxV1: defaultInbox)
notice "Client started", client = c.ident.getId(), notice "Client started", client = c.ident.getId(),
default_inbox = default_inbox defaultInbox = defaultInbox
result = c result = c
################################################# #################################################
@ -90,18 +90,18 @@ proc newClient*(name: string, cfg: WakuConfig): Client =
proc getId(client: Client): string = proc getId(client: Client): string =
result = client.ident.getId() result = client.ident.getId()
proc default_inbox_conversation_id*(self: Client): string = proc defaultInboxConversationId*(self: Client): string =
## Returns the default inbox address for the client. ## Returns the default inbox address for the client.
result = conversation_id_for(self.ident.getPubkey()) result = conversationIdFor(self.ident.getPubkey())
proc getConversationFromHint(self: Client, proc getConversationFromHint(self: Client,
conversation_hint: string): Result[Option[ConvoWrapper], string] = conversationHint: string): Result[Option[ConvoWrapper], string] =
# TODO: Implementing Hinting # TODO: Implementing Hinting
if not self.conversations.hasKey(conversation_hint): if not self.conversations.hasKey(conversationHint):
ok(none(ConvoWrapper)) ok(none(ConvoWrapper))
else: else:
ok(some(self.conversations[conversation_hint])) ok(some(self.conversations[conversationHint]))
################################################# #################################################
@ -113,16 +113,17 @@ proc createIntroBundle*(self: var Client): IntroBundle =
## the required information to send a message. ## the required information to send a message.
# Create Ephemeral keypair, save it in the key store # Create Ephemeral keypair, save it in the key store
let ephemeral_key = generate_key() let ephemeralKey = generateKey()
self.key_store[ephemeral_key.getPublickey().bytes().bytesToHex()] = KeyEntry(
keytype: "ephemeral", self.keyStore[ephemeralKey.getPublicKey().bytes().bytesToHex()] = KeyEntry(
privateKey: ephemeral_key, keyType: "ephemeral",
privateKey: ephemeralKey,
timestamp: getTimestamp() timestamp: getTimestamp()
) )
result = IntroBundle( result = IntroBundle(
ident: @(self.ident.getPubkey().bytes()), ident: @(self.ident.getPubkey().bytes()),
ephemeral: @(ephemeral_key.getPublicKey().bytes()), ephemeral: @(ephemeralKey.getPublicKey().bytes()),
) )
notice "IntroBundleCreated", client = self.getId(), notice "IntroBundleCreated", client = self.getId(),
@ -143,42 +144,43 @@ proc createPrivateConversation(client: Client, participant: PublicKey,
notice "Creating PrivateV1 conversation", topic = convo.getConvoId() notice "Creating PrivateV1 conversation", topic = convo.getConvoId()
client.conversations[convo.getConvoId()] = ConvoWrapper( client.conversations[convo.getConvoId()] = ConvoWrapper(
convo_type: PrivateV1Type, convoType: PrivateV1Type,
privateV1: convo privateV1: convo
) )
return some(convo.getConvoId()) return some(convo.getConvoId())
proc newPrivateConversation*(client: Client, proc newPrivateConversation*(client: Client,
intro_bundle: IntroBundle): Future[Option[ChatError]] {.async.} = introBundle: IntroBundle): Future[Option[ChatError]] {.async.} =
## Creates a private conversation with the given `IntroBundle`. ## Creates a private conversation with the given `IntroBundle`.
## `IntroBundles` are provided out-of-band. ## `IntroBundles` are provided out-of-band.
notice "New PRIVATE Convo ", clientId = client.getId(), notice "New PRIVATE Convo ", clientId = client.getId(),
fromm = intro_bundle.ident.mapIt(it.toHex(2)).join("") fromm = introBundle.ident.mapIt(it.toHex(2)).join("")
let res_pubkey = loadPublicKeyFromBytes(intro_bundle.ident) let pubkeyResult = loadPublicKeyFromBytes(introBundle.ident)
if res_pubkey.isErr: if pubkeyResult.isErr:
raise newException(ValueError, "Invalid public key in intro bundle.") raise newException(ValueError, "Invalid public key in intro bundle.")
let dest_pubkey = res_pubkey.get() let destPubkey = pubkeyResult.get()
let convo_id = conversation_id_for(dest_pubkey)
let dst_convo_topic = topic_inbox(dest_pubkey.get_addr()) let convoId = conversationIdFor(destPubkey)
let destConvoTopic = topicInbox(destPubkey.getAddr())
let invite = InvitePrivateV1( let invite = InvitePrivateV1(
initiator: @(client.ident.getPubkey().bytes()), initiator: @(client.ident.getPubkey().bytes()),
initiator_ephemeral: @[0, 0], # TODO: Add ephemeral initiatorEphemeral: @[0, 0], # TODO: Add ephemeral
participant: @(dest_pubkey.bytes()), participant: @(destPubkey.bytes()),
participant_ephemeral_id: intro_bundle.ephemeral_id, participantEphemeralId: introBundle.ephemeralId,
discriminator: "test" discriminator: "test"
) )
let env = wrap_env(encrypt(InboxV1Frame(invite_private_v1: invite, let env = wrapEnv(encrypt(InboxV1Frame(invitePrivateV1: invite,
recipient: "")), convo_id) recipient: "")), convoId)
let convo = createPrivateConversation(client, dest_pubkey) discard createPrivateConversation(client, destPubkey)
# TODO: Subscribe to new content topic # TODO: Subscribe to new content topic
await client.ds.sendPayload(dst_convo_topic, env) await client.ds.sendPayload(destConvoTopic, env)
return none(ChatError) return none(ChatError)
proc acceptPrivateInvite(client: Client, proc acceptPrivateInvite(client: Client,
@ -188,12 +190,12 @@ proc acceptPrivateInvite(client: Client,
notice "ACCEPT PRIVATE Convo ", clientId = client.getId(), notice "ACCEPT PRIVATE Convo ", clientId = client.getId(),
fromm = invite.initiator.mapIt(it.toHex(2)).join("") fromm = invite.initiator.mapIt(it.toHex(2)).join("")
let res_pubkey = loadPublicKeyFromBytes(invite.initiator) let pubkeyResult = loadPublicKeyFromBytes(invite.initiator)
if res_pubkey.isErr: if pubkeyResult.isErr:
raise newException(ValueError, "Invalid public key in intro bundle.") raise newException(ValueError, "Invalid public key in intro bundle.")
let dest_pubkey = res_pubkey.get() let destPubkey = pubkeyResult.get()
let convo = createPrivateConversation(client, dest_pubkey) discard createPrivateConversation(client, destPubkey)
# TODO: Subscribe to new content topic # TODO: Subscribe to new content topic
result = none(ChatError) result = none(ChatError)
@ -207,12 +209,12 @@ proc handleInboxFrame(client: Client, frame: InboxV1Frame) =
## Dispatcher for Incoming `InboxV1Frames`. ## Dispatcher for Incoming `InboxV1Frames`.
## Calls further processing depending on the kind of frame. ## Calls further processing depending on the kind of frame.
case getKind(frame): case getKind(frame):
of type_InvitePrivateV1: of typeInvitePrivateV1:
notice "Receive PrivateInvite", client = client.getId(), notice "Receive PrivateInvite", client = client.getId(),
frame = frame.invite_private_v1 frame = frame.invitePrivateV1
discard client.acceptPrivateInvite(frame.invite_private_v1) discard client.acceptPrivateInvite(frame.invitePrivateV1)
of type_Note: of typeNote:
notice "Receive Note", text = frame.note.text notice "Receive Note", text = frame.note.text
# TODO: These handle function need symmetry, currently have different signatures # TODO: These handle function need symmetry, currently have different signatures
@ -223,10 +225,10 @@ proc handlePrivateFrame(client: Client, convo: PrivateV1, bytes: seq[byte]) =
let frame = convo.decrypt(enc) # TODO: handle result let frame = convo.decrypt(enc) # TODO: handle result
case frame.getKind(): case frame.getKind():
of type_ContentFrame: of typeContentFrame:
notice "Got Mail", client = client.getId(), notice "Got Mail", client = client.getId(),
text = frame.content.bytes.toUtfString() text = frame.content.bytes.toUtfString()
of type_Placeholder: of typePlaceholder:
notice "Got Placeholder", client = client.getId(), notice "Got Placeholder", client = client.getId(),
text = frame.placeholder.counter text = frame.placeholder.counter
@ -235,26 +237,26 @@ proc parseMessage(client: Client, msg: ChatPayload) =
info "Parse", clientId = client.getId(), msg = msg, info "Parse", clientId = client.getId(), msg = msg,
contentTopic = msg.contentTopic contentTopic = msg.contentTopic
let res_env = decode(msg.bytes, WapEnvelopeV1) let resEnv = decode(msg.bytes, WapEnvelopeV1)
if res_env.isErr: if resEnv.isErr:
raise newException(ValueError, "Failed to decode WapEnvelopeV1: " & res_env.error) raise newException(ValueError, "Failed to decode WapEnvelopeV1: " & resEnv.error)
let env = res_env.get() let env = resEnv.get()
let res_convo = client.getConversationFromHint(env.conversation_hint) let resConvo = client.getConversationFromHint(env.conversationHint)
if res_convo.isErr: if resConvo.isErr:
raise newException(ValueError, "Failed to get conversation: " & raise newException(ValueError, "Failed to get conversation: " &
res_convo.error) resConvo.error)
let resWrappedConvo = res_convo.get() let resWrappedConvo = resConvo.get()
if not resWrappedConvo.isSome: if not resWrappedConvo.isSome:
let k = toSeq(client.conversations.keys()).join(", ") let k = toSeq(client.conversations.keys()).join(", ")
warn "No conversation found", client = client.getId(), warn "No conversation found", client = client.getId(),
hint = env.conversation_hint, knownIds = k hint = env.conversationHint, knownIds = k
return return
let wrappedConvo = resWrappedConvo.get() let wrappedConvo = resWrappedConvo.get()
case wrappedConvo.convo_type: case wrappedConvo.convoType:
of InboxV1Type: of InboxV1Type:
let enc = decode(env.payload, EncryptedPayload).get() # TODO: handle result let enc = decode(env.payload, EncryptedPayload).get() # TODO: handle result
let resFrame = inbox.decrypt(enc) # TODO: handle result let resFrame = inbox.decrypt(enc) # TODO: handle result
@ -266,7 +268,7 @@ proc parseMessage(client: Client, msg: ChatPayload) =
client.handleInboxFrame(resFrame.get()) client.handleInboxFrame(resFrame.get())
of PrivateV1Type: of PrivateV1Type:
client.handlePrivateFrame(wrapped_convo.private_v1, env.payload) client.handlePrivateFrame(wrappedConvo.privateV1, env.payload)
proc addMessage*(client: Client, convo: PrivateV1, proc addMessage*(client: Client, convo: PrivateV1,
text: string = "") {.async.} = text: string = "") {.async.} =
@ -303,14 +305,14 @@ proc simulateMessages(client: Client){.async.} =
# TODO: FutureBug - This should wait for a privateV1 conversation. # TODO: FutureBug - This should wait for a privateV1 conversation.
while client.conversations.len() <= 1: while client.conversations.len() <= 1:
await sleepAsync(4000) await sleepAsync(4.seconds)
notice "Starting Message Simulation", client = client.getId() notice "Starting Message Simulation", client = client.getId()
for a in 1..5: for a in 1..5:
await sleepAsync(4000) await sleepAsync(4.seconds)
for convoWrapper in client.conversations.values(): for convoWrapper in client.conversations.values():
if convoWrapper.convo_type == PrivateV1Type: if convoWrapper.convoType == PrivateV1Type:
await client.addMessage(convoWrapper.privateV1, fmt"message: {a}") await client.addMessage(convoWrapper.privateV1, fmt"message: {a}")
################################################# #################################################