From c3eeff9d0670f04e8da2d2d7df3bf7ccbf16cadc Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 12 Sep 2024 07:08:50 -0400 Subject: [PATCH] chore: add fetch-protos to aid in proto updates Signed-off-by: Brandon McAnsh --- .../com/getcode/model/chat/MessageContent.kt | 4 +- .../repository/TransactionRepository.kt | 8 +- .../repository/TransactionRepository_Swap.kt | 4 +- scripts/fetch-protos.sh | 38 ++ scripts/strip-proto-validation.sh | 43 ++ .../main/proto/badge/v1/badge_service.proto | 4 - .../src/main/proto/chat/v1/chat_service.proto | 135 ++++--- .../src/main/proto/chat/v2/chat_service.proto | 207 +++------- .../src/main/proto/common/v1/model.proto | 49 +-- .../contact/v1/contact_list_service.proto | 19 +- .../proto/currency/v1/currency_service.proto | 6 +- .../main/proto/device/v1/device_service.proto | 15 +- .../main/proto/invite/v2/invite_service.proto | 18 +- .../messaging/v1/messaging_service.proto | 77 +--- .../v1/micro_payment_service.proto | 15 +- .../phone/v1/phone_verification_service.proto | 17 +- .../src/main/proto/push/v1/push_service.proto | 35 +- .../transaction/v2/transaction_service.proto | 366 ++++-------------- .../main/proto/user/v1/identity_service.proto | 50 +-- 19 files changed, 359 insertions(+), 751 deletions(-) create mode 100755 scripts/fetch-protos.sh create mode 100755 scripts/strip-proto-validation.sh diff --git a/api/src/main/java/com/getcode/model/chat/MessageContent.kt b/api/src/main/java/com/getcode/model/chat/MessageContent.kt index 83036a72a..d9dd7e054 100644 --- a/api/src/main/java/com/getcode/model/chat/MessageContent.kt +++ b/api/src/main/java/com/getcode/model/chat/MessageContent.kt @@ -340,9 +340,9 @@ sealed interface MessageContent { proto: MessageContentV1, ): MessageContent? { return when (proto.typeCase) { - ChatServiceV1.Content.TypeCase.LOCALIZED -> Localized( + ChatServiceV1.Content.TypeCase.SERVER_LOCALIZED -> Localized( isFromSelf = false, - value = proto.localized.keyOrText + value = proto.serverLocalized.keyOrText ) ChatServiceV1.Content.TypeCase.EXCHANGE_DATA -> { diff --git a/api/src/main/java/com/getcode/network/repository/TransactionRepository.kt b/api/src/main/java/com/getcode/network/repository/TransactionRepository.kt index 9a65b20d7..05a79bc7c 100644 --- a/api/src/main/java/com/getcode/network/repository/TransactionRepository.kt +++ b/api/src/main/java/com/getcode/network/repository/TransactionRepository.kt @@ -368,8 +368,8 @@ class TransactionRepository @Inject constructor( expected?.diff(produced) } - TransactionService.ErrorDetails.TypeCase.INTENT_DENIED -> { - errors.add("Denied: ${error.intentDenied.reason.name}") + TransactionService.ErrorDetails.TypeCase.DENIED -> { + errors.add("Denied: ${error.denied.reason}") } else -> Unit } @@ -765,8 +765,8 @@ sealed class ErrorSubmitIntent(val value: Int) { return when (proto.code) { SubmitIntentResponse.Error.Code.DENIED -> { val reasons = proto.errorDetailsList.mapNotNull { - if (!it.hasIntentDenied()) return@mapNotNull null - DeniedReason.fromValue(it.intentDenied.reasonValue) + if (!it.hasDenied()) return@mapNotNull null + DeniedReason.fromValue(it.denied.codeValue) } Denied(reasons) diff --git a/api/src/main/java/com/getcode/network/repository/TransactionRepository_Swap.kt b/api/src/main/java/com/getcode/network/repository/TransactionRepository_Swap.kt index dc5d8f177..2933e978e 100644 --- a/api/src/main/java/com/getcode/network/repository/TransactionRepository_Swap.kt +++ b/api/src/main/java/com/getcode/network/repository/TransactionRepository_Swap.kt @@ -91,8 +91,8 @@ private suspend fun TransactionRepository.submit(intent: SwapIntent): Result { - errors.add("Denied: ${error.intentDenied.reason.name}") + TransactionService.ErrorDetails.TypeCase.DENIED -> { + errors.add("Denied: ${error.denied.reason}") } else -> Unit } diff --git a/scripts/fetch-protos.sh b/scripts/fetch-protos.sh new file mode 100755 index 000000000..43aa24b92 --- /dev/null +++ b/scripts/fetch-protos.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +root=$(pwd) +REPO_URL="https://github.com/code-payments/code-protobuf-api" +COMMIT_SHA=$1 +TEMP_DIR=$(mktemp -d) +DEST_DIR="service/protos/src/main/proto" + +# Clone the repository +git clone "$REPO_URL" "$TEMP_DIR" + +# Change to the cloned repository directory +cd "$TEMP_DIR" || exit + +# If a commit SHA is provided, checkout that commit +if [ -n "$COMMIT_SHA" ]; then + git checkout "$COMMIT_SHA" +else + git checkout main +fi + +# Create the destination directory if it doesn't exist +mkdir -p "../../$DEST_DIR" + +# Copy proto files +if [ -d "proto" ]; then + rsync -av --exclude='buf*' proto/ "${root}/$DEST_DIR/" + echo "Proto files copied successfully." +else + echo "Error: 'proto' directory not found in the repository." + exit 1 +fi + +# Clean up: remove the temporary directory +cd ../.. +rm -rf "$TEMP_DIR" + +sh "${root}"/scripts/strip-proto-validation.sh diff --git a/scripts/strip-proto-validation.sh b/scripts/strip-proto-validation.sh new file mode 100755 index 000000000..10c99af5d --- /dev/null +++ b/scripts/strip-proto-validation.sh @@ -0,0 +1,43 @@ +# +# For all .proto files, strip the validation parameters & replace inline +# + +root=$(pwd) + +# 1. hack: first add a couple newlines after all "];" +find "${root}"/service/protos/src/main/proto -name "*.proto" -type f -exec sh -c "awk '{gsub(/];/, \"];\n\n\"); print}' {} > tmp && mv tmp {}" \; + +# 2. strip everything between square brackets [...] ignoring lines starting with // +find "${root}"/service/protos/src/main/proto -name "*.proto" -type f -exec sh -c "awk '!/^[[:space:]]*\/\// {gsub(/ \[.*\]/, \"\");} {print}' {} > tmp && mv tmp {}" \; + +find "${root}"/service/protos/src/main/proto -name "*.proto" -type f | while read -r file; do + awk ' + BEGIN { in_repeated = 0; buffer = "" } + { + if ($0 ~ /^[[:space:]]*(repeated|bytes|[A-Za-z0-9_]+).*=.*\[/) { + in_repeated = 1 + buffer = $0 + } else if (in_repeated) { + buffer = buffer " " $0 + } + + if (in_repeated && $0 ~ /;/) { + gsub(/\[.*\]/, "", buffer) + print buffer + in_repeated = 0 + buffer = "" + } else if (!in_repeated && $0 !~ /^[[:space:]]*option[[:space:]]*\(validate\.required\)[[:space:]]*=[[:space:]]*true;/) { + print $0 + } + } + ' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file" +done + +# 3. add a newline after all trailing } brackets +#find "${root}"/service/protos/src/main/proto -name "*.proto" -type f -exec sh -c "awk '{gsub(/}/, \"}\n\"); print}' {} > tmp && mv tmp {}" \; + +# 4. strip validate import statement +find "${root}"/service/protos/src/main/proto -name "*.proto" -type f -exec sh -c "awk -v RS='' '{gsub(/import \"validate\/validate.proto\";/, \"\"); print}' {} > tmp && mv tmp {}" \; + +# 5. add a newline after all trailing } brackets +#find "${root}"/service/protos/src/main/proto -name "*.proto" -type f -exec sh -c "awk '{gsub(/}/, \"}\n\"); print}' {} > tmp && mv tmp {}" \; \ No newline at end of file diff --git a/service/protos/src/main/proto/badge/v1/badge_service.proto b/service/protos/src/main/proto/badge/v1/badge_service.proto index 63ee68ca6..6b67b6c64 100644 --- a/service/protos/src/main/proto/badge/v1/badge_service.proto +++ b/service/protos/src/main/proto/badge/v1/badge_service.proto @@ -8,7 +8,6 @@ service Badge { // ResetBadgeCount resets an owner account's app icon badge count back to zero rpc ResetBadgeCount(ResetBadgeCountRequest) returns (ResetBadgeCountResponse); } - message ResetBadgeCountRequest { // The owner account to clear badge count common.v1.SolanaAccountId owner = 1; @@ -17,12 +16,9 @@ message ResetBadgeCountRequest { // mechanism to the RPC. common.v1.Signature signature = 2; } - message ResetBadgeCountResponse { Result result = 1; enum Result { OK = 0; } - } - diff --git a/service/protos/src/main/proto/chat/v1/chat_service.proto b/service/protos/src/main/proto/chat/v1/chat_service.proto index e06036dc4..0d95aa619 100644 --- a/service/protos/src/main/proto/chat/v1/chat_service.proto +++ b/service/protos/src/main/proto/chat/v1/chat_service.proto @@ -6,6 +6,7 @@ option objc_class_prefix = "CPBChatV1"; import "common/v1/model.proto"; import "transaction/v2/transaction_service.proto"; import "google/protobuf/timestamp.proto"; +// Deprecated: Use the v2 service service Chat { // GetChats gets the set of chats for an owner account rpc GetChats(GetChatsRequest) returns (GetChatsResponse); @@ -17,8 +18,12 @@ service Chat { rpc SetMuteState(SetMuteStateRequest) returns (SetMuteStateResponse); // SetSubscriptionState configures the susbscription state of a chat rpc SetSubscriptionState(SetSubscriptionStateRequest) returns (SetSubscriptionStateResponse); + // + // Experimental PoC two-way chat APIs below + // + rpc StreamChatEvents(stream StreamChatEventsRequest) returns (stream StreamChatEventsResponse); + rpc SendMessage(SendMessageRequest) returns (SendMessageResponse); } - message GetChatsRequest { common.v1.SolanaAccountId owner = 1; common.v1.Signature signature = 2; @@ -29,19 +34,15 @@ message GetChatsRequest { ASC = 0; DESC = 1; } - } - message GetChatsResponse { Result result = 1; enum Result { OK = 0; NOT_FOUND = 1; } - - repeated ChatMetadata chats = 2; + repeated ChatMetadata chats = 2 ; } - message GetMessagesRequest { ChatId chat_id = 1; common.v1.SolanaAccountId owner = 2; @@ -53,26 +54,21 @@ message GetMessagesRequest { ASC = 0; DESC = 1; } - } - message GetMessagesResponse { Result result = 1; enum Result { OK = 0; NOT_FOUND = 1; } - - repeated ChatMessage messages = 2; + repeated ChatMessage messages = 2 ; } - message AdvancePointerRequest { ChatId chat_id = 1; Pointer pointer = 2; common.v1.SolanaAccountId owner = 3; common.v1.Signature signature = 4; } - message AdvancePointerResponse { Result result = 1; enum Result { @@ -80,16 +76,13 @@ message AdvancePointerResponse { CHAT_NOT_FOUND = 1; MESSAGE_NOT_FOUND = 2; } - } - message SetMuteStateRequest { ChatId chat_id = 1; bool is_muted = 2; common.v1.SolanaAccountId owner = 3; common.v1.Signature signature = 4; } - message SetMuteStateResponse { Result result = 1; enum Result { @@ -97,16 +90,13 @@ message SetMuteStateResponse { CHAT_NOT_FOUND = 1; CANT_MUTE = 2; } - } - message SetSubscriptionStateRequest { ChatId chat_id = 1; bool is_subscribed = 2; common.v1.SolanaAccountId owner = 3; common.v1.Signature signature = 4; } - message SetSubscriptionStateResponse { Result result = 1; enum Result { @@ -114,36 +104,73 @@ message SetSubscriptionStateResponse { CHAT_NOT_FOUND = 1; CANT_UNSUBSCRIBE = 2; } - } - +message OpenChatEventStream { + ChatId chat_id = 1; + common.v1.SolanaAccountId owner = 2; + common.v1.Signature signature = 3; +} +message ChatStreamEvent { + repeated ChatMessage messages = 1; + repeated Pointer pointers = 2; +} +message ChatStreamEventBatch { + repeated ChatStreamEvent events = 2 ; +} +message StreamChatEventsRequest { + oneof type { + OpenChatEventStream open_stream = 1; + common.v1.ClientPong pong = 2; + } +} +message StreamChatEventsResponse { + oneof type { + ChatStreamEventBatch events = 1; + common.v1.ServerPing ping = 2; + } +} +message SendMessageRequest { + common.v1.SolanaAccountId owner = 1; + common.v1.Signature signature = 2; + ChatId chat_id = 3; + // todo: What field type should this be? Maybe the chat message itself with fields missing? + repeated Content content = 4 ; +} +message SendMessageResponse { + Result result = 1; + enum Result { + OK = 0; + } + ChatMessage message = 2; +} message ChatId { - bytes value = 1; + bytes value = 1 ; } - message ChatMessageId { - bytes value = 1; + bytes value = 1 ; +} +message ChatMemberId { + // todo: Public key for now + bytes value = 1 ; } - message Pointer { Kind kind = 1; enum Kind { - UNKNOWN = 0; - READ = 1; + UNKNOWN = 0; + READ = 1; + DELIVERED = 2; + SENT = 3; // Probably always inferred by OK result in SendMessageResponse } - ChatMessageId value = 2; + ChatMemberId user = 3; } - message ChatMetadata { ChatId chat_id = 1; // Recommended chat title inferred by the type of chat oneof title { - - LocalizedContent localized = 2; - common.v1.Domain domain = 3; + ServerLocalizedContent localized = 2; + common.v1.Domain domain = 3; } - // Pointer in the chat indicating the most recently read message by the user Pointer read_pointer = 4; // Estimated number of unread messages in this chat @@ -156,7 +183,7 @@ message ChatMetadata { bool can_mute = 8; // Can the user unsubscribe from this chat? bool can_unsubscribe = 9; - // Cursor value for this chat for reference in subsequent GetChatsRequest + // Cursor value for this chat for reference in subsequent GetChatsRequest Cursor cursor = 10; // Is this a verified chat? // @@ -164,34 +191,31 @@ message ChatMetadata { // different verification statuses. They should be treated separately. bool is_verified = 11; } - message ChatMessage { // Unique ID for this message ChatMessageId message_id = 1; // Timestamp this message was generated at google.protobuf.Timestamp ts = 2; // Ordered message content. A message may have more than one piece of content. - repeated Content content = 3; - // Cursor value for this message for reference in subsequent GetMessagesRequest + repeated Content content = 3 ; + // Cursor value for this message for reference in subsequent GetMessagesRequest Cursor cursor = 4; + ChatMemberId sender = 5; } - message Content { oneof type { - - LocalizedContent localized = 1; - ExchangeDataContent exchange_data = 2; - NaclBoxEncryptedContent nacl_box = 3; + ServerLocalizedContent server_localized = 1; + ExchangeDataContent exchange_data = 2; + NaclBoxEncryptedContent nacl_box = 3; + TextContent text = 4; + ThankYouContent thank_you = 5; } - } - -message LocalizedContent { +message ServerLocalizedContent { // When server-side localization is in place, clients will always see the // localized text. - string key_or_text = 1; + string key_or_text = 1 ; } - message ExchangeDataContent { Verb verb = 1; enum Verb { @@ -208,23 +232,24 @@ message ExchangeDataContent { RECEIVED_TIP = 10; SENT_TIP = 11; } - oneof exchange_data { - transaction.v2.ExchangeData exact = 2; transaction.v2.ExchangeDataWithoutRate partial = 3; } - } - message NaclBoxEncryptedContent { common.v1.SolanaAccountId peer_public_key = 1; - bytes nonce = 2; - bytes encrypted_payload = 3; + bytes nonce = 2 ; + bytes encrypted_payload = 3 ; +} +message TextContent { + string text = 1 ; +} +message ThankYouContent { + // todo: May need additional metdata (who is being thanked, which tip, etc) } - // Opaque cursor used across paged APIs. Underlying bytes may change as paging // strategies evolve. message Cursor { - bytes value = 1; -} \ No newline at end of file + bytes value = 1 ; +} diff --git a/service/protos/src/main/proto/chat/v2/chat_service.proto b/service/protos/src/main/proto/chat/v2/chat_service.proto index d428c50b9..022bff99f 100644 --- a/service/protos/src/main/proto/chat/v2/chat_service.proto +++ b/service/protos/src/main/proto/chat/v2/chat_service.proto @@ -1,23 +1,17 @@ syntax = "proto3"; - package code.chat.v2; - option go_package = "github.com/code-payments/code-protobuf-api/generated/go/chat/v2;chat"; option java_package = "com.codeinc.gen.chat.v2"; option objc_class_prefix = "CPBChatV2"; - import "common/v1/model.proto"; import "transaction/v2/transaction_service.proto"; import "google/protobuf/timestamp.proto"; - service Chat { // GetChats gets the set of chats for an owner account using a paged API. // This RPC is aware of all identities tied to the owner account. rpc GetChats(GetChatsRequest) returns (GetChatsResponse); - // GetMessages gets the set of messages for a chat member using a paged API rpc GetMessages(GetMessagesRequest) returns (GetMessagesResponse); - // StreamChatEvents streams chat events in real-time. Chat events include // messages, pointer updates, etc. // @@ -49,74 +43,57 @@ service Chat { // they are observed. Events sent over the stream should not affect the ping/pong // protocol timings. rpc StreamChatEvents(stream StreamChatEventsRequest) returns (stream StreamChatEventsResponse); - // StartChat starts a chat. The RPC call is idempotent and will use existing // chats whenever applicable within the context of message routing. rpc StartChat(StartChatRequest) returns (StartChatResponse); - // SendMessage sends a message to a chat rpc SendMessage(SendMessageRequest) returns (SendMessageResponse); - // AdvancePointer advances a pointer in message history for a chat member rpc AdvancePointer(AdvancePointerRequest) returns (AdvancePointerResponse); - // RevealIdentity reveals a chat member's identity if it is anonymous. A chat // message will be inserted on success. rpc RevealIdentity(RevealIdentityRequest) returns (RevealIdentityResponse); - // SetMuteState configures a chat member's mute state rpc SetMuteState(SetMuteStateRequest) returns (SetMuteStateResponse); - // SetSubscriptionState configures a chat member's susbscription state rpc SetSubscriptionState(SetSubscriptionStateRequest) returns (SetSubscriptionStateResponse); + // NotifyIsTypingRequest notifies a chat that the sending member is typing. + // + // These requests are transient, and may be dropped at any point. + rpc NotifyIsTyping(NotifyIsTypingRequest) returns (NotifyIsTypingResponse); } - message GetChatsRequest { common.v1.SolanaAccountId owner = 1; - common.v1.Signature signature = 2; - uint32 page_size = 3; - Cursor cursor = 4; - Direction direction = 5; enum Direction { ASC = 0; DESC = 1; } } - message GetChatsResponse { Result result = 1; enum Result { OK = 0; NOT_FOUND = 1; } - - repeated ChatMetadata chats = 2; + repeated ChatMetadata chats = 2 ; } - message GetMessagesRequest { ChatId chat_id = 1; - ChatMemberId member_id = 2; - common.v1.SolanaAccountId owner = 3; - common.v1.Signature signature = 4; - uint32 page_size = 5; - Cursor cursor = 6; - Direction direction = 7; enum Direction { ASC = 0; DESC = 1; } } - message GetMessagesResponse { Result result = 1; enum Result { @@ -125,32 +102,24 @@ message GetMessagesResponse { CHAT_NOT_FOUND = 2; MESSAGE_NOT_FOUND = 3; } - - repeated ChatMessage messages = 2; + repeated ChatMessage messages = 2 ; } - message OpenChatEventStream { ChatId chat_id = 1; - - ChatMemberId member_id = 2; - + ChatMemberId member_id = 2 ; common.v1.SolanaAccountId owner = 3; - common.v1.Signature signature = 4; } - message ChatStreamEvent { oneof type { - ChatMessage message = 1; Pointer pointer = 2; + IsTyping is_typing = 3; } } - message ChatStreamEventBatch { - repeated ChatStreamEvent events = 2; + repeated ChatStreamEvent events = 2 ; } - message ChatStreamEventError { Code code = 1; enum Code { @@ -158,36 +127,27 @@ message ChatStreamEventError { CHAT_NOT_FOUND = 1; } } - message StreamChatEventsRequest { oneof type { - OpenChatEventStream open_stream = 1; common.v1.ClientPong pong = 2; } } - message StreamChatEventsResponse { oneof type { - ChatStreamEventBatch events = 1; common.v1.ServerPing ping = 2; ChatStreamEventError error = 3; } } - message StartChatRequest { common.v1.SolanaAccountId owner = 1; - common.v1.Signature signature = 2; - oneof parameters { - StartTipChatParameters tip_chat = 3; // GroupChatParameters group_chat = 4; } } - // Starts a two-way chat between a tipper and tippee. Chat members are // inferred from the 12 word public keys involved in the intent. Only // the tippee can start the chat, and the tipper is anonymous if this @@ -197,7 +157,6 @@ message StartTipChatParameters { // an ExchangeDataContent message content where the verb is RECEIVED_TIP. common.v1.IntentId intent_id = 1; } - message StartChatResponse { Result result = 1; enum Result { @@ -205,26 +164,19 @@ message StartChatResponse { DENIED = 1; INVALID_PARAMETER = 2; } - // The chat to use if the RPC was successful ChatMetadata chat = 2; } - message SendMessageRequest { ChatId chat_id = 1; - - ChatMemberId member_id = 2; - + ChatMemberId member_id = 2 ; // Allowed content types that can be sent by client: // - TextContent // - ThankYouContent - repeated Content content = 3; - + repeated Content content = 3 ; common.v1.SolanaAccountId owner = 4; - common.v1.Signature signature = 5; } - message SendMessageResponse { Result result = 1; enum Result { @@ -234,22 +186,16 @@ message SendMessageResponse { INVALID_CHAT_TYPE = 3; INVALID_CONTENT_TYPE = 4; } - // The chat message that was sent if the RPC was succesful, which includes // server-side metadata like the generated message ID and official timestamp ChatMessage message = 2; } - message AdvancePointerRequest { ChatId chat_id = 1; - Pointer pointer = 2; - common.v1.SolanaAccountId owner = 3; - common.v1.Signature signature = 4; } - message AdvancePointerResponse { Result result = 1; enum Result { @@ -260,19 +206,13 @@ message AdvancePointerResponse { INVALID_POINTER_TYPE = 4; } } - message RevealIdentityRequest { ChatId chat_id = 1; - ChatMemberId member_id = 2; - ChatMemberIdentity identity = 3; - common.v1.SolanaAccountId owner = 4; - common.v1.Signature signature = 5; } - message RevealIdentityResponse { Result result = 1; enum Result { @@ -281,23 +221,16 @@ message RevealIdentityResponse { CHAT_NOT_FOUND = 2; DIFFERENT_IDENTITY_REVEALED = 3; } - // The chat message that was sent if the RPC was successful ChatMessage message = 2; } - message SetMuteStateRequest { ChatId chat_id = 1; - - ChatMemberId member_id = 2; - + ChatMemberId member_id = 2 ; bool is_muted = 3; - common.v1.SolanaAccountId owner = 4; - common.v1.Signature signature = 5; } - message SetMuteStateResponse { Result result = 1; enum Result { @@ -307,19 +240,13 @@ message SetMuteStateResponse { CANT_MUTE = 3; } } - message SetSubscriptionStateRequest { ChatId chat_id = 1; - - ChatMemberId member_id = 2; - + ChatMemberId member_id = 2 ; bool is_subscribed = 3; - common.v1.SolanaAccountId owner = 4; - common.v1.Signature signature = 5; } - message SetSubscriptionStateResponse { Result result = 1; enum Result { @@ -329,57 +256,62 @@ message SetSubscriptionStateResponse { CANT_UNSUBSCRIBE = 3; } } - +message NotifyIsTypingRequest { + ChatId chat_id = 1; + ChatMemberId member_id = 2 ; + bool is_typing = 3; + common.v1.SolanaAccountId owner = 4; + common.v1.Signature signature = 5; +} +message NotifyIsTypingResponse { + Result result = 1; + enum Result { + OK = 0; + DENIED = 1; + CHAT_NOT_FOUND = 2; + } +} message ChatId { // Sufficient space is left for a consistent hash value, though other types // of values may be used. - bytes value = 1; + bytes value = 1 ; } - message ChatMessageId { // Guaranteed to be a time-based UUID. This should be used to construct a // consistently ordered message history based on time using a simple byte // comparison. - bytes value = 1; + bytes value = 1 ; } - message ChatMemberId { // Globally random UUID - bytes value = 1; + bytes value = 1 ; } - enum ChatType { UNKNOWN_CHAT_TYPE = 0; NOTIFICATION = 1; TWO_WAY = 2; // GROUP = 3; } - enum Platform { UNKNOWN_PLATFORM = 0; TWITTER = 1; } - enum PointerType { UNKNOWN_POINTER_TYPE = 0; SENT = 1; // Always inferred by OK result in SendMessageResponse or message presence in a chat DELIVERED = 2; READ = 3; } - // A chat // // todo: Support is_verified in a clean way message ChatMetadata { // Globally unique ID for this chat ChatId chat_id = 1; - // The type of chat - ChatType type = 2; - + ChatType type = 2 ; // The chat title, which will be localized by server when applicable - string title = 3; - + string title = 3 ; // The members in this chat // // For NOTIFICATION chats, this list has exactly 1 item @@ -388,100 +320,80 @@ message ChatMetadata { // todo: If we support group chats, then we'll likely return the first page // or a prioritized list. The remaining members would be fetched via // a new RPC. - repeated ChatMember members = 4; - + repeated ChatMember members = 4 ; // Can the user mute this chat? bool can_mute = 5; - // Can the user unsubscribe from this chat? bool can_unsubscribe = 6; - // Cursor value for this chat for reference in subsequent GetChatsRequest Cursor cursor = 7; } - // A message in a chat message ChatMessage { // Globally unique ID for this message ChatMessageId message_id = 1; - // The chat member that sent the message. For NOTIFICATION chats, this field // is omitted since the chat has exactly 1 member. ChatMemberId sender_id = 2; - // Ordered message content. A message may have more than one piece of content. - repeated Content content = 3; - + repeated Content content = 3 ; // Timestamp this message was generated at. This value is also encoded in // any time-based UUID message IDs. google.protobuf.Timestamp ts = 4; - // Cursor value for this message for reference in a paged GetMessagesRequest Cursor cursor = 5; } - // A user in a chat message ChatMember { // Globally unique ID for this chat member ChatMemberId member_id = 1; - // Is this chat member yourself? This enables client to identify which member_id // is themselves. bool is_self = 2; - // The chat member's identity if it has been revealed. ChatMemberIdentity identity = 3; - // Chat message state for this member. This list will have DELIVERED and READ // pointers, if they exist. SENT pointers should be inferred by persistence // on server. - repeated Pointer pointers = 4; - + repeated Pointer pointers = 4 ; // Estimated number of unread messages for the chat member in this chat // // Only valid when is_self = true uint32 num_unread = 5; - // Has the chat member muted this chat? // // Only valid when is_self = true bool is_muted = 6; - // Is the chat member subscribed to this chat? // // Only valid when is_self = true bool is_subscribed = 7; } - // Identity to an external social platform that can be linked to a Code account message ChatMemberIdentity { // The external social platform linked to this chat member - Platform platform = 1; - + Platform platform = 1 ; // The chat member's username on the external social platform - string username = 2; + string username = 2 ; + // If present, the URL of the users profile pic. + string profile_pic_url = 3 ; } - // Pointer in a chat indicating a user's message history state in a chat. message Pointer { // The type of pointer indicates which user's message history state can be // inferred from the pointer value. It is also possible to infer cross-pointer // state. For example, if a chat member has a READ pointer for a message with // ID N, then the DELIVERED pointer must be at least N. - PointerType type = 1; - + PointerType type = 1 ; // Everything at or before this message ID is considered to have the state // inferred by the type of pointer. ChatMessageId value = 2; - // The chat member associated with this pointer state ChatMemberId member_id = 3; } - // Content for a chat message message Content { oneof type { - TextContent text = 1; LocalizedContent localized = 2; ExchangeDataContent exchange_data = 3; @@ -490,18 +402,15 @@ message Content { IdentityRevealedContent identity_revealed = 6; } } - // Raw text content message TextContent { - string text = 1; + string text = 1 ; } - // Text content that is either a localization key that should be translated on // client, or a server-side translated piece of text. message LocalizedContent { - string key_or_text = 1; + string key_or_text = 1 ; } - // Exchange data content for movement of a value of Kin message ExchangeDataContent { enum Verb { @@ -518,69 +427,61 @@ message ExchangeDataContent { RECEIVED_TIP = 10; SENT_TIP = 11; } - // Verb describing how the amount of Kin was exchanged // // Note: The current definition is not suitable outside a NOTIFICATION chat // as not enough context is provided as to which member this verb is // associated with. - Verb verb = 1; - + Verb verb = 1 ; // An amount of Kin being exchanged oneof exchange_data { - transaction.v2.ExchangeData exact = 2; transaction.v2.ExchangeDataWithoutRate partial = 3; } - // An ID that can be referenced to the source of the exchange of Kin oneof reference { - common.v1.IntentId intent = 4; common.v1.Signature signature = 5; } } - // Encrypted piece of content using NaCl box encryption message NaclBoxEncryptedContent { // The sender's public key that is used to derive the shared private key for // decryption for message content. common.v1.SolanaAccountId peer_public_key = 1; - // Globally random nonce that is unique to this encrypted piece of content - bytes nonce = 2; - + bytes nonce = 2 ; // The encrypted piece of message content - bytes encrypted_payload = 3; + bytes encrypted_payload = 3 ; } - // Thank you content that is used to thank Code users for tips message ThankYouContent { // The tip intent that is being thanked. common.v1.IntentId tip_intent = 1; - // Reserved for the thanker, which is only required if we support GROUP chats. // Otherwise, it can be inferred from the sender in a TWO_WAY chat. reserved 2; - // Reserved for the thankee, which is only required if we support GROUP chats. // Otherwise, it can be inferred from the sender in a TWO_WAY chat. reserved 3; } - // Identity revealed content that is inserted into chat whenever a chat member // reveals their identity message IdentityRevealedContent { // The chat member who revealed their identity ChatMemberId member_id = 1; - // The identity that was revealed ChatMemberIdentity identity = 2; } - // Opaque cursor used across paged APIs. Underlying bytes may change as paging // strategies evolve. Expected length value will vary based on the RPC being // executed. message Cursor { - bytes value = 1; -} \ No newline at end of file + bytes value = 1 ; +} +message IsTyping { + ChatMemberId member_id = 1; + // is_typing indicates whether or not the user is typing. + // If false, the user has explicitly stopped typing. + bool is_typing = 2; +} diff --git a/service/protos/src/main/proto/common/v1/model.proto b/service/protos/src/main/proto/common/v1/model.proto index aeb81df0b..70aab885c 100644 --- a/service/protos/src/main/proto/common/v1/model.proto +++ b/service/protos/src/main/proto/common/v1/model.proto @@ -3,10 +3,8 @@ package code.common.v1; option go_package = "github.com/code-payments/code-protobuf-api/generated/go/common/v1;common"; option java_package = "com.codeinc.gen.common.v1"; option objc_class_prefix = "CPBCommonV1"; - import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; - // AccountType associates a type to an account, which infers how an account is used // within the Code ecosystem. enum AccountType { @@ -26,12 +24,10 @@ enum AccountType { RELATIONSHIP = 13; SWAP = 14; } - // SolanaAccountId is a raw binary Ed25519 public key for a Solana account message SolanaAccountId { - bytes value = 1; + bytes value = 1 ; } - // InstructionAccount is an account public key used within the context of // an instruction. message InstructionAccount { @@ -39,89 +35,73 @@ message InstructionAccount { bool is_signer = 2; bool is_writable = 3; } - // Transaction is a raw binary Solana transaction message Transaction { // Maximum size taken from: https://github.com/solana-labs/solana/blob/39b3ac6a8d29e14faa1de73d8b46d390ad41797b/sdk/src/packet.rs#L9-L13 - bytes value = 1; + bytes value = 1 ; } - // Blockhash is a raw binary Solana blockchash message Blockhash { - bytes value = 1; + bytes value = 1 ; } - // Signature is a raw binary Ed25519 signature message Signature { - bytes value = 1; + bytes value = 1 ; } - // IntentId is a client-side generated ID that maps to an intent to perform actions // on the blockchain fulfilled by the Code sequencer. message IntentId { - bytes value = 1; + bytes value = 1 ; } - // UserId is a globally unique identifier for a user within Code // // Note: Users outside Code are modelled as relationship accounts message UserId { - bytes value = 1; + bytes value = 1 ; } - // DataContainerId is a globally unique identifier for a container where a user // can store a copy of their data message DataContainerId { - bytes value = 1; + bytes value = 1 ; } - // DeviceToken is an opaque token used to verify whether a device real message DeviceToken { - string value = 1; + string value = 1 ; } - // AppInstallId is a unque ID tied to a client app installation. It does not // identify a device. Value should remain private and not be shared across // installs. message AppInstallId { - string value = 1; + string value = 1 ; } - // PhoneNumber is an E.164 phone number message PhoneNumber { // Regex provided by Twilio here: https://www.twilio.com/docs/glossary/what-e164#regex-matching-for-e164 string value = 1; } - // Domain is a hostname message Domain { - string value = 1; + string value = 1 ; } - // Relationship is a set of identifiers that a user can establish a relationship // with. message Relationship { oneof type { common.v1.Domain domain = 1; } - } - // Hash is a raw binary 32 byte hash value message Hash { - bytes value = 1; + bytes value = 1 ; } - // Locale is a user locale consisting of a combination of language, script and region message Locale { string value = 1; } - // UUID is a 16 byte UUID value message UUID { - bytes value = 1; + bytes value = 1 ; } - // Request is a generic wrapper for gRPC requests message Request { string version = 1; @@ -129,7 +109,6 @@ message Request { string method = 3; bytes body = 4; } - // Response is a generic wrapper for gRPC responses message Response { Result result = 1; @@ -140,19 +119,15 @@ message Response { ERROR = 1; } } - message ServerPing { // Timestamp the ping was sent on the stream, for client to get a sense // of potential network latency google.protobuf.Timestamp timestamp = 1; - // The delay server will apply before sending the next ping google.protobuf.Duration ping_delay = 2; } - message ClientPong { // Timestamp the Pong was sent on the stream, for server to get a sense // of potential network latency google.protobuf.Timestamp timestamp = 1; } - diff --git a/service/protos/src/main/proto/contact/v1/contact_list_service.proto b/service/protos/src/main/proto/contact/v1/contact_list_service.proto index 3bcb70924..4fd312c2e 100644 --- a/service/protos/src/main/proto/contact/v1/contact_list_service.proto +++ b/service/protos/src/main/proto/contact/v1/contact_list_service.proto @@ -12,7 +12,6 @@ service ContactList { // GetContacts gets a subset of contacts from a user's contact list rpc GetContacts(GetContactsRequest) returns (GetContactsResponse); } - message AddContactsRequest { // The public key of the owner account that signed this request message. common.v1.SolanaAccountId owner_account_id = 1; @@ -23,22 +22,19 @@ message AddContactsRequest { // The data container for the copy of the contact list being added to. common.v1.DataContainerId container_id = 3; // The set of contacts to add to the contact list - repeated common.v1.PhoneNumber contacts = 4; + repeated common.v1.PhoneNumber contacts = 4 ; } - message AddContactsResponse { Result result = 1; enum Result { OK = 0; } - // The contacts' current status keyed by phone number. This is an optimization // so that clients can populate initial state without needing an extra network // call. map contact_status = 2; } - message RemoveContactsRequest { // The public key of the owner account that signed this request message. common.v1.SolanaAccountId owner_account_id = 1; @@ -49,17 +45,14 @@ message RemoveContactsRequest { // The data container for the copy of the contact list being removed from. common.v1.DataContainerId container_id = 3; // The set of contacts to remove from the contact list - repeated common.v1.PhoneNumber contacts = 4; + repeated common.v1.PhoneNumber contacts = 4 ; } - message RemoveContactsResponse { Result result = 1; enum Result { OK = 0; } - } - message GetContactsRequest { // The public key of the owner account that signed this request message. common.v1.SolanaAccountId owner_account_id = 1; @@ -76,13 +69,11 @@ message GetContactsRequest { // that have both been invited and registered with the app. bool include_only_in_app_contacts = 5; } - message GetContactsResponse { Result result = 1; enum Result { OK = 0; } - // A page of contacts repeated Contact contacts = 2; // The page token to include in a subsequent request to get the next set of @@ -90,14 +81,12 @@ message GetContactsResponse { // pages. PageToken next_page_token = 3; } - message Contact { // The contact's phone number common.v1.PhoneNumber phone_number = 1; // The contact's current status ContactStatus status = 2; } - message ContactStatus { // Flag to indicate whether a user has registered with Code and used the app // at least once. @@ -111,8 +100,6 @@ message ContactStatus { // todo: This field will be deprecated after the invite phase is complete. bool is_invite_revoked = 3; } - message PageToken { - bytes value = 1; + bytes value = 1 ; } - diff --git a/service/protos/src/main/proto/currency/v1/currency_service.proto b/service/protos/src/main/proto/currency/v1/currency_service.proto index 8cafaab0e..0f8f86277 100644 --- a/service/protos/src/main/proto/currency/v1/currency_service.proto +++ b/service/protos/src/main/proto/currency/v1/currency_service.proto @@ -8,14 +8,12 @@ service Currency { // GetAllRates returns the exchange rates for Kin against all available currencies rpc GetAllRates(GetAllRatesRequest) returns (GetAllRatesResponse); } - message GetAllRatesRequest { // If timestamp is included, the returned rate will be the most recent available // exchange rate prior to the provided timestamp within the same day. Otherwise, // the latest rates will be returned. google.protobuf.Timestamp timestamp = 1; } - message GetAllRatesResponse { Result result = 1; enum Result { @@ -23,10 +21,8 @@ message GetAllRatesResponse { // No currency data is available for the requested timestamp. MISSING_DATA = 1; } - // The time the exchange rates were observed google.protobuf.Timestamp as_of = 2; // The price of 1 Kin in different currencies, keyed on 3- or 4- letter lowercase currency code. - map rates = 3; + map rates = 3 ; } - diff --git a/service/protos/src/main/proto/device/v1/device_service.proto b/service/protos/src/main/proto/device/v1/device_service.proto index 1a1a96def..04d1b8783 100644 --- a/service/protos/src/main/proto/device/v1/device_service.proto +++ b/service/protos/src/main/proto/device/v1/device_service.proto @@ -14,42 +14,35 @@ service Device { // Clients can use this RPC to detect stale logins for boot out of the app. rpc GetLoggedInAccounts(GetLoggedInAccountsRequest) returns (GetLoggedInAccountsResponse); } - message RegisterLoggedInAccountsRequest { common.v1.AppInstallId app_install = 1; // The set of owners logged into the app install. Setting an empty value // indicates there are no logged in users. We allow for more than one owner // in the spec with a repeated field to be flexible in the future. - repeated common.v1.SolanaAccountId owners = 2; + repeated common.v1.SolanaAccountId owners = 2 ; // Signature values must appear in the exact order their respecitive signing // owner account appears in the owners field. All signatures should be generated // without any other signature values set. - repeated common.v1.Signature signatures = 3; + repeated common.v1.Signature signatures = 3 ; } - message RegisterLoggedInAccountsResponse { Result result = 1; enum Result { OK = 0; INVALID_OWNER = 1; } - // Set of invalid owner accounts detected in the request. An owner account // can be invalid for several reasons: not phone verified, timelock account // unlocked, etc. Value is set when result is INVALID_OWNER. - repeated common.v1.SolanaAccountId invalid_owners = 2; + repeated common.v1.SolanaAccountId invalid_owners = 2 ; } - message GetLoggedInAccountsRequest { common.v1.AppInstallId app_install = 1; } - message GetLoggedInAccountsResponse { Result result = 1; enum Result { OK = 0; } - - repeated common.v1.SolanaAccountId owners = 2; + repeated common.v1.SolanaAccountId owners = 2 ; } - diff --git a/service/protos/src/main/proto/invite/v2/invite_service.proto b/service/protos/src/main/proto/invite/v2/invite_service.proto index e887c429f..99f73857e 100644 --- a/service/protos/src/main/proto/invite/v2/invite_service.proto +++ b/service/protos/src/main/proto/invite/v2/invite_service.proto @@ -14,33 +14,27 @@ service Invite { // GetInvitationStatus gets a phone number's invitation status. rpc GetInvitationStatus(GetInvitationStatusRequest) returns (GetInvitationStatusResponse); } - message GetInviteCountRequest { // The user to query for their invite count common.v1.UserId user_id = 1; } - message GetInviteCountResponse { Result result = 1; enum Result { OK = 0; } - // The number of invites the user is allowed to issue. uint32 invite_count = 2; } - message InvitePhoneNumberRequest { // The source for the invite. One of these values must be present oneof source { common.v1.UserId user = 1; InviteCode invite_code = 3; } - // The phone number receiving the invite. common.v1.PhoneNumber receiver = 2; } - message InvitePhoneNumberResponse { Result result = 1; enum Result { @@ -63,33 +57,26 @@ message InvitePhoneNumberResponse { // The invite code has expired. INVITE_CODE_EXPIRED = 7; } - } - message GetInvitationStatusRequest { // The user being queried for their invitation status. common.v1.UserId user_id = 1; } - message GetInvitationStatusResponse { Result result = 1; enum Result { OK = 0; } - // The user's invitation status InvitationStatus status = 2; } - message InviteCode { // Regex for invite codes - string value = 1; + string value = 1 ; } - message PageToken { - bytes value = 1; + bytes value = 1 ; } - enum InvitationStatus { // The phone number has never been invited. NOT_INVITED = 0; @@ -101,4 +88,3 @@ enum InvitationStatus { // The phone number was invited, but revoked at a later time. REVOKED = 3; } - diff --git a/service/protos/src/main/proto/messaging/v1/messaging_service.proto b/service/protos/src/main/proto/messaging/v1/messaging_service.proto index 0f713c0f8..1eb32863b 100644 --- a/service/protos/src/main/proto/messaging/v1/messaging_service.proto +++ b/service/protos/src/main/proto/messaging/v1/messaging_service.proto @@ -1,15 +1,11 @@ syntax = "proto3"; - package code.messaging.v1; - option go_package = "github.com/code-payments/code-protobuf-api/generated/go/messaging/v1;messaging"; option java_package = "com.codeinc.gen.messaging.v1"; option objc_class_prefix = "CPBMessagingV1"; - import "common/v1/model.proto"; import "transaction/v2/transaction_service.proto"; import "google/protobuf/timestamp.proto"; - service Messaging { // OpenMessageStream opens a stream of messages. Messages are routed using the // public key of a rendezvous keypair derived by both the sender and the @@ -62,7 +58,6 @@ service Messaging { // WebhookCalled) for login state. // 7. The third party closes the stream once the login hits a terminal state, or times out. rpc OpenMessageStream(OpenMessageStreamRequest) returns (stream OpenMessageStreamResponse); - // OpenMessageStreamWithKeepAlive is like OpenMessageStream, but enables a ping/pong // keepalive to determine the health of the stream at both the client and server. // @@ -89,7 +84,6 @@ service Messaging { // Note: This API will enforce OpenMessageStreamRequest.signature is set as part of migration // to this newer protocol rpc OpenMessageStreamWithKeepAlive(stream OpenMessageStreamWithKeepAliveRequest) returns (stream OpenMessageStreamWithKeepAliveResponse); - // PollMessages is like OpenMessageStream, but uses a polling flow for receiving // messages. Updates are not real-time and depedent on the polling interval. // This RPC supports all message types. @@ -97,101 +91,80 @@ service Messaging { // This is a temporary RPC until OpenMessageStream can be built out generically on // both client and server, while supporting things like multiple listeners. rpc PollMessages(PollMessagesRequest) returns (PollMessagesResponse); - // AckMessages acks one or more messages that have been successfully delivered to // the client. rpc AckMessages(AckMessagesRequest) returns (AckMesssagesResponse); - // SendMessage sends a message. rpc SendMessage(SendMessageRequest) returns (SendMessageResponse); } - message OpenMessageStreamRequest { RendezvousKey rendezvous_key = 1; - // The signature is of serialize(OpenMessageStreamRequest) using rendezvous_key. // // todo: Make required once clients migrate common.v1.Signature signature = 2; } - message OpenMessageStreamResponse { - repeated Message messages = 1; + repeated Message messages = 1 ; } - message OpenMessageStreamWithKeepAliveRequest { oneof request_or_pong { OpenMessageStreamRequest request = 1; common.v1.ClientPong pong = 2; } } - message OpenMessageStreamWithKeepAliveResponse { - oneof responseOrPing { + oneof response_or_ping { OpenMessageStreamResponse response = 1; common.v1.ServerPing ping = 2; } } - message PollMessagesRequest { RendezvousKey rendezvous_key = 1; - // The signature is of serialize(PollMessagesRequest) using rendezvous_key. common.v1.Signature signature = 2; } - message PollMessagesResponse { - repeated Message messages = 1; + repeated Message messages = 1 ; } - message AckMessagesRequest { RendezvousKey rendezvous_key = 1; - - repeated MessageId message_ids = 2; + repeated MessageId message_ids = 2 ; } - message AckMesssagesResponse { Result result = 1; enum Result { OK = 0; } } - message SendMessageRequest { // The message to send. Types of messages clients can send are restricted. Message message = 1; - // The rendezvous key that the message should be routed to. RendezvousKey rendezvous_key = 2; - // The signature is of serialize(Message) using the PrivateKey of the keypair. common.v1.Signature signature = 3; } - message SendMessageResponse { Result result = 1; enum Result { OK = 0; NO_ACTIVE_STREAM = 1; } - // Set if result == OK. MessageId message_id = 2; } - // RendezvousKey is a unique key pair, typically derived from a scan code payload, // which is used to establish a secure communication channel anonymously to coordinate // a flow using messages. message RendezvousKey { - bytes value = 1; + bytes value = 1 ; } - // MessageId identifies a message. It is only guaranteed to be unique when // paired with a destination (i.e. the rendezvous public key). message MessageId { - bytes value = 1; + bytes value = 1 ; } - // Request that a pulled out bill be sent to the requested address. // // This message type is only initiated by clients. @@ -199,7 +172,6 @@ message RequestToGrabBill { // Requestor is the Kin token account on Solana to which a payment should be sent. common.v1.SolanaAccountId requestor_account = 1; } - // Request that a bill of a requested value is created and sent to the requested // address. // @@ -207,16 +179,13 @@ message RequestToGrabBill { message RequestToReceiveBill { // Requestor is the Kin token account on Solana to which a payment should be sent. common.v1.SolanaAccountId requestor_account = 1; - // The exchange data for the requested bill value. oneof exchange_data { - // An exact amount of Kin. Payment is guaranteed to transfer the specified // quarks in the requested currency and exchange rate. // // Only supports Kin. Use exchange_data.partial for fiat amounts. transaction.v2.ExchangeData exact = 2; - // Fiat amount request. The amount of Kin is determined at time of payment // with a recent exchange rate provided by the paying client and validatd // by server. @@ -224,7 +193,6 @@ message RequestToReceiveBill { // Only supports fiat amounts. Use exchange_data.exact for Kin. transaction.v2.ExchangeDataWithoutRate partial = 3; } - // // Optional fields below to identify a domain requesting to receive a bill. // Verification of the domain is optional. When verified, clients can establish @@ -235,26 +203,20 @@ message RequestToReceiveBill { // - Verified: All of domain, verifier, signature and rendezvous_key are required // - Unverified: Only domain is requried // - // The third-party's domain name, which is its primary identifier. Server // guarantees to perform domain verification against the verifier account. common.v1.Domain domain = 4; - // Owner account owned by the third party used in domain verification. common.v1.SolanaAccountId verifier = 5; - // Signature of this message using the verifier private key, which in addition // to domain verification, authenticates the third party. common.v1.Signature signature = 6; - // Rendezvous key to avoid replay attacks RendezvousKey rendezvous_key = 7; - // Additional fee payments splitting the requested amount. This is in addition // to the hard-coded Code $0.01 USD fee. repeated transaction.v2.AdditionalFeePayment additional_fees = 8; } - // A status update on a stream to indicate a scan code was scanned. This can appear // multiple times for the same stream. // @@ -263,25 +225,21 @@ message CodeScanned { // Timestamp the client scanned the code google.protobuf.Timestamp timestamp = 1; } - // Payment is rejected by the client // // This message type is only initiated by clients message ClientRejectedPayment { common.v1.IntentId intent_id = 1; } - // Intent was submitted via SubmitIntent // // This message type is only initiated by server message IntentSubmitted { common.v1.IntentId intent_id = 1; - // Metadata is available for intents where it can be safely propagated publicly. // Anything else requires an additional authenticated RPC call (eg. login). transaction.v2.Metadata metadata = 2; } - // Webhook was successfully called // // This message type is only initiated by server @@ -289,8 +247,6 @@ message WebhookCalled { // Estimated time webhook was received google.protobuf.Timestamp timestamp = 1; } - - // Request that an account logs in // // This message type is only initiated by third-parties through the SDK. @@ -301,25 +257,19 @@ message RequestToLogin { // Clients should expect subdomains for future feature compatiblity, but must // use the ASCII base domain in the RELATIONSHIP account derivation strategy. common.v1.Domain domain = 1; - // Deprecated nonce value, which is replaced by the rendezvous_key field which // is effectively derived off a random nonce. reserved 2; - // Reserved for a timestamp field, which may be used in the future. reserved 3; - // Owner account owned by the third party used in domain verification. common.v1.SolanaAccountId verifier = 4; - // Signature of this message using the verifier private key, which in addition // to domain verification, authenticates the third party. common.v1.Signature signature = 5; - // Rendezvous key to avoid replay attacks RendezvousKey rendezvous_key = 6; } - // Login is rejected by the client // // This message type is only initiated by user clients @@ -327,21 +277,17 @@ message ClientRejectedLogin { // Timestamp the login was rejected google.protobuf.Timestamp timestamp = 4; } - // Client has received an aidrop from server // // This message type is only initiated by server. message AirdropReceived { // The type of airdrop received transaction.v2.AirdropType airdrop_type = 1; - // Exchange data relating to the amount of Kin and fiat value of the airdrop transaction.v2.ExchangeData exchange_data = 2; - // Time the airdrop was received google.protobuf.Timestamp timestamp = 3; } - message Message { // MessageId is the Id of the message. This ID is generated by the // server, and will _always_ be set when receiving a message. @@ -350,43 +296,34 @@ message Message { // 1. Reserve the ability for any future ID changes // 2. Prevent clients attempting to collide message IDs. MessageId id = 1; - // The signature sent from SendMessageRequest, which will be injected by server. // This enables clients to ensure no MITM attacks were performed to hijack contents // of the typed message. This is only applicable for messages not generated by server. common.v1.Signature send_message_request_signature = 3; - // Next field number is 13 oneof kind { // // Section: Cash // - RequestToGrabBill request_to_grab_bill = 2; - // // Section: Payment Requests // - RequestToReceiveBill request_to_receive_bill = 5; CodeScanned code_scanned = 6; ClientRejectedPayment client_rejected_payment = 7; IntentSubmitted intent_submitted = 8; WebhookCalled webhook_called = 9; - // // Section: Login // - RequestToLogin request_to_login = 10; ClientRejectedLogin client_rejected_login = 12; - // // Section: Airdrops // - AirdropReceived airdrop_received = 4; } // Reserved for deprecated LoginAttempt field reserved 11; -} \ No newline at end of file +} diff --git a/service/protos/src/main/proto/micropayment/v1/micro_payment_service.proto b/service/protos/src/main/proto/micropayment/v1/micro_payment_service.proto index 696ac3049..a4cf15021 100644 --- a/service/protos/src/main/proto/micropayment/v1/micro_payment_service.proto +++ b/service/protos/src/main/proto/micropayment/v1/micro_payment_service.proto @@ -23,11 +23,9 @@ service MicroPayment { // it's sole design is to enable PoC and trials. rpc GetPathMetadata(GetPathMetadataRequest) returns (GetPathMetadataResponse); } - message GetStatusRequest { common.v1.IntentId intent_id = 1; } - message GetStatusResponse { // Does the payment request exist? bool exists = 1; @@ -36,10 +34,9 @@ message GetStatusResponse { // Has the user sumbmitted a payment? bool intent_submitted = 3; } - message RegisterWebhookRequest { common.v1.IntentId intent_id = 1; - string url = 2; + string url = 2 ; } message RegisterWebhookResponse { Result result = 1; @@ -54,12 +51,10 @@ message RegisterWebhookResponse { // The webhook URL is invalid INVALID_URL = 4; } - } - message CodifyRequest { // The URL to Codify - string url = 1; + string url = 1 ; // ISO 4217 alpha-3 currency code the payment should be made in string currency = 2; // The amount that should be paid in the native currency @@ -74,7 +69,6 @@ message CodifyRequest { // to the RPC and can be used to validate payment details. common.v1.Signature signature = 6; } - message CodifyResponse { Result result = 1; enum Result { @@ -88,22 +82,18 @@ message CodifyResponse { // The payment amount exceeds the minimum/maximum allowed amount NATIVE_AMOUNT_EXCEEDS_LIMIT = 4; } - // The URL to view the content with a Code micro paywall string codified_url = 2; } - message GetPathMetadataRequest { string path = 1; } - message GetPathMetadataResponse { Result result = 1; enum Result { OK = 0; NOT_FOUND = 1; } - // The account where the payment should be sent to common.v1.SolanaAccountId destination = 2; @@ -114,4 +104,3 @@ message GetPathMetadataResponse { // The URL to redirect upon successful payment string redirct_url = 5; } - diff --git a/service/protos/src/main/proto/phone/v1/phone_verification_service.proto b/service/protos/src/main/proto/phone/v1/phone_verification_service.proto index 53dde133e..63f37b75c 100644 --- a/service/protos/src/main/proto/phone/v1/phone_verification_service.proto +++ b/service/protos/src/main/proto/phone/v1/phone_verification_service.proto @@ -15,14 +15,12 @@ service PhoneVerification { // GetAssociatedPhoneNumber gets the latest verified phone number linked to an owner account. rpc GetAssociatedPhoneNumber(GetAssociatedPhoneNumberRequest) returns (GetAssociatedPhoneNumberResponse); } - message SendVerificationCodeRequest { // The phone number to send a verification code over SMS to. common.v1.PhoneNumber phone_number = 1; // Device token for antispam measures against fake devices common.v1.DeviceToken device_token = 2; } - message SendVerificationCodeResponse { Result result = 1; enum Result { @@ -39,21 +37,21 @@ message SendVerificationCodeResponse { // The phone number is not real because it fails Twilio lookup. INVALID_PHONE_NUMBER = 3; // The phone number is valid, but it maps to an unsupported type of phone - // like a landline or ESIM. + // like a landline or eSIM. UNSUPPORTED_PHONE_TYPE = 4; // The country associated with the phone number is not supported (eg. it // is on the sanctioned list). UNSUPPORTED_COUNTRY = 5; + // The device is not supported (eg. it fails device attestation checks) + UNSUPPORTED_DEVICE = 6; } } - message CheckVerificationCodeRequest { // The phone number being verified. common.v1.PhoneNumber phone_number = 1; // The verification code received via SMS. VerificationCode code = 2; } - message CheckVerificationCodeResponse { Result result = 1; enum Result { @@ -71,12 +69,10 @@ message CheckVerificationCodeResponse { // not verified. RATE_LIMITED = 3; } - // The token used to associate an owner account to a user using the verified // phone number. PhoneLinkingToken linking_token = 2; } - message GetAssociatedPhoneNumberRequest { // The public key of the owner account that is being queried for a linked // phone number. @@ -86,7 +82,6 @@ message GetAssociatedPhoneNumberRequest { // an authentication mechanism to the RPC. common.v1.Signature signature = 2; } - message GetAssociatedPhoneNumberResponse { Result result = 1; enum Result { @@ -98,7 +93,6 @@ message GetAssociatedPhoneNumberResponse { // The phone number exists, but at least one timelock account is unlocked UNLOCKED_TIMELOCK_ACCOUNT = 3; } - // The latest phone number associated with the owner account. common.v1.PhoneNumber phone_number = 2; // State that determines whether a phone number is linked to the owner @@ -107,12 +101,10 @@ message GetAssociatedPhoneNumberResponse { // of whether the number was linked at any point in time. bool is_linked = 3; } - message VerificationCode { // A 4-10 digit numerical code. - string value = 2; + string value = 2 ; } - // A one-time use token that can be provided to the Identity service to link an // owner account to a user with the verified phone number. The client should // treat this token as opaque. @@ -122,4 +114,3 @@ message PhoneLinkingToken { // The code that verified the phone number. VerificationCode code = 2; } - diff --git a/service/protos/src/main/proto/push/v1/push_service.proto b/service/protos/src/main/proto/push/v1/push_service.proto index fbccb73da..de3cac502 100644 --- a/service/protos/src/main/proto/push/v1/push_service.proto +++ b/service/protos/src/main/proto/push/v1/push_service.proto @@ -9,9 +9,16 @@ service Push { // and adding an existing valid token will not fail. Token types will be // validated against the user agent and any mismatches will result in an // INVALID_ARGUMENT status error. + // + // The token will be unlinked from any and all other accounts that it was + // previously bound to. rpc AddToken(AddTokenRequest) returns (AddTokenResponse); + // RemoveToken removes the provided push token from the account. + // + // The provided token must be bound to the current account. + // Otherwise, the RPC will succeed with without removal. + rpc RemoveToken(RemoveTokenRequest) returns (RemoveTokenResponse); } - enum TokenType { UNKNOWN = 0; // FCM registration token for an Android device @@ -19,7 +26,6 @@ enum TokenType { // FCM registration token or an iOS device FCM_APNS = 2; } - message AddTokenRequest { // The public key of the owner account that signed this request message. common.v1.SolanaAccountId owner_account_id = 1; @@ -30,14 +36,13 @@ message AddTokenRequest { // The data container where the push token will be stored. common.v1.DataContainerId container_id = 3; // The push token to store - string push_token = 4; + string push_token = 4 ; // The type of push token TokenType token_type = 5; // The instance of the app install where the push token was generated. Ideally, // the push token is unique to the install. common.v1.AppInstallId app_install = 6; } - message AddTokenResponse { Result result = 1; enum Result { @@ -45,6 +50,24 @@ message AddTokenResponse { // The push token is invalid and wasn't stored. INVALID_PUSH_TOKEN = 1; } - } - +message RemoveTokenRequest { + // The public key of the owner account that signed this request message. + common.v1.SolanaAccountId owner_account_id = 1; + // The signature is of serialize(AddTokenRequest) without this field set + // using the private key of owner_account_id. This provides an authentication + // mechanism to the RPC. + common.v1.Signature signature = 2; + // The data container where the push token was stored. + common.v1.DataContainerId container_id = 3; + // The push token to remove. + string push_token = 4 ; + // The type of push token to remove. + TokenType token_type = 5; +} +message RemoveTokenResponse { + Result result = 1; + enum Result { + OK = 0; + } +} diff --git a/service/protos/src/main/proto/transaction/v2/transaction_service.proto b/service/protos/src/main/proto/transaction/v2/transaction_service.proto index 66f720c57..143716e8b 100644 --- a/service/protos/src/main/proto/transaction/v2/transaction_service.proto +++ b/service/protos/src/main/proto/transaction/v2/transaction_service.proto @@ -1,14 +1,10 @@ syntax = "proto3"; - package code.transaction.v2; - option go_package = "github.com/code-payments/code-protobuf-api/generated/go/transaction/v2;transaction"; option java_package = "com.codeinc.gen.transaction.v2"; option objc_class_prefix = "APBTransactionV2"; - import "common/v1/model.proto"; import "google/protobuf/timestamp.proto"; - service Transaction { // SubmitIntent is the mechanism for client and server to agree upon a set of // client actions to execute on the blockchain using the Code sequencer for @@ -43,36 +39,28 @@ service Transaction { // * Server will return SubmitIntentResponse.Error and close the stream // * Client will close the stream rpc SubmitIntent(stream SubmitIntentRequest) returns (stream SubmitIntentResponse); - // GetIntentMetadata gets basic metadata on an intent. It can also be used // to fetch the status of submitted intents. Metadata exists only for intents // that have been successfully submitted. rpc GetIntentMetadata(GetIntentMetadataRequest) returns (GetIntentMetadataResponse); - // GetPrivacyUpgradeStatus gets the status of a private transaction and the // ability to upgrade it to permanent privacy. rpc GetPrivacyUpgradeStatus(GetPrivacyUpgradeStatusRequest) returns (GetPrivacyUpgradeStatusResponse); - // GetPrioritizedIntentsForPrivacyUpgrade allows clients to get private // intent actions that can be upgraded in a secure and verifiable manner. rpc GetPrioritizedIntentsForPrivacyUpgrade(GetPrioritizedIntentsForPrivacyUpgradeRequest) returns (GetPrioritizedIntentsForPrivacyUpgradeResponse); - // GetLimits gets limits for money moving intents for an owner account in an // identity-aware manner rpc GetLimits(GetLimitsRequest) returns (GetLimitsResponse); - // GetPaymentHistory gets an owner account's payment history inferred from intents // // Deprecated: Payment history has migrated to chats rpc GetPaymentHistory(GetPaymentHistoryRequest) returns (GetPaymentHistoryResponse); - // CanWithdrawToAccount provides hints to clients for submitting withdraw intents. // The RPC indicates if a withdrawal is possible, and how it should be performed. rpc CanWithdrawToAccount(CanWithdrawToAccountRequest) returns (CanWithdrawToAccountResponse); - // Airdrop airdrops Kin to the requesting account rpc Airdrop(AirdropRequest) returns (AirdropResponse); - // Swap performs an on-chain swap. The high-level flow mirrors SubmitIntent // closely. However, due to the time-sensitive nature and unreliability of // swaps, they do not fit within the broader intent system. This results in @@ -92,109 +80,63 @@ service Transaction { // Note: Currently limited to swapping USDC to Kin. // Note: Kin is deposited into the primary account. rpc Swap(stream SwapRequest) returns (stream SwapResponse); - // DeclareFiatOnrampPurchaseAttempt is called whenever a user attempts to use a fiat // onramp to purchase crypto for use in Code. rpc DeclareFiatOnrampPurchaseAttempt(DeclareFiatOnrampPurchaseAttemptRequest) returns (DeclareFiatOnrampPurchaseAttemptResponse); } - -message DeclareFiatOnrampPurchaseAttemptRequest { - // The owner account invoking the buy module - common.v1.SolanaAccountId owner = 1; - - // The amount being purchased - ExchangeDataWithoutRate purchase_amount = 2; - - // A nonce value unique to the purchase. If it's included in a memo for the - // transaction for the deposit to the owner, then purchase_amount will be used - // for display values. Otherwise, the amount will be inferred from the transaction. - common.v1.UUID nonce = 3; - - // The signature is of serialize(DeclareFiatOnrampPurchaseAttemptRequest) without - // this field set using the private key of the owner account. This provides an - // authentication mechanism to the RPC. - common.v1.Signature signature = 4; -} - -message DeclareFiatOnrampPurchaseAttemptResponse { - Result result = 1; - enum Result { - OK = 0; - // The owner account is not valid (ie. it isn't a Code account) - INVALID_OWNER = 1; - // The currency isn't supported - UNSUPPORTED_CURRENCY = 2; - // The amount specified exceeds limits - AMOUNT_EXCEEDS_MAXIMUM = 3; - } -} - // // Request and Response Definitions // - message SubmitIntentRequest { oneof request { SubmitActions submit_actions = 1; SubmitSignatures submit_signatures = 2; } - message SubmitActions { // The globally unique client generated intent ID. Use the original intent // ID when operating on actions that mutate the intent. common.v1.IntentId id = 1; - + // The verified owner account public key common.v1.SolanaAccountId owner = 2; - // Additional metadata that describes the high-level intention Metadata metadata = 3; - // The set of all ordered actions required to fulfill the intent - repeated Action actions = 4; - + repeated Action actions = 4 ; // The signature is of serialize(SubmitActions) without this field set using the // private key of the owner account. This provides an authentication mechanism // to the RPC. common.v1.Signature signature = 5; - // Device token for antispam measures against fake devices common.v1.DeviceToken device_token = 6; } - message SubmitSignatures { // The set of all signatures for each transaction requiring signature from the // authority accounts. - repeated common.v1.Signature signatures = 1; + repeated common.v1.Signature signatures = 1 ; } } - message SubmitIntentResponse { oneof response { - ServerParameters server_parameters = 1; Success success = 2; Error error = 3; } - message ServerParameters { // The set of all server paremeters required to fill missing transaction // details. Server guarantees to provide a message for each client action - // in an order consistent with the received action list. - repeated ServerParameter server_parameters = 1; + // in an order consistent with the received action list. + repeated ServerParameter server_parameters = 1 ; } - message Success { Code code = 1; enum Code { // The intent was successfully created and is now scheduled. OK = 0; } - - // todo: Revisit if we need side-effects. Clients are effecitively doing - // local simulation now with the privacy solution. + // todo: Revisit if we need side-effects. Clients are effecitively doing + // local simulation now with the privacy solution. } - message Error { Code code = 1; enum Code { @@ -207,43 +149,34 @@ message SubmitIntentResponse { // Server detected client has stale state. STALE_STATE = 3; } - repeated ErrorDetails error_details = 2; } } - message GetIntentMetadataRequest { // The intent ID to query common.v1.IntentId intent_id = 1; - // The verified owner account public key when not signing with the rendezvous // key. Only owner accounts involved in the intent can access the metadata. common.v1.SolanaAccountId owner = 2; - // The signature is of serialize(GetIntentStatusRequest) without this field set // using the private key of the rendezvous or owner account. This provides an // authentication mechanism to the RPC. common.v1.Signature signature = 3; } - message GetIntentMetadataResponse { Result result = 1; enum Result { OK = 0; NOT_FOUND = 1; } - Metadata metadata = 2; } - message GetPrivacyUpgradeStatusRequest { // The intent ID common.v1.IntentId intent_id = 1; - // The action ID for private transaction uint32 action_id = 2; } - message GetPrivacyUpgradeStatusResponse { Result result = 1; enum Result { @@ -255,7 +188,6 @@ message GetPrivacyUpgradeStatusResponse { // The provided action doesn't map to a private transaction INVALID_ACTION = 3; } - Status status = 2; enum Status { UNKNOWN = 0; @@ -271,106 +203,83 @@ message GetPrivacyUpgradeStatusResponse { ALREADY_UPGRADED = 4; } } - message GetPrioritizedIntentsForPrivacyUpgradeRequest { // The owner account to query against for upgradeable intents. common.v1.SolanaAccountId owner = 1; - // The maximum number of intents to return in the response. Default is 10. uint32 limit = 2; - // The signature is of serialize(GetPrioritizedIntentsForPrivacyUpgradeRequest) // without this field set using the private key of the owner account. This // provides an authentication mechanism to the RPC. common.v1.Signature signature = 3; } - message GetPrioritizedIntentsForPrivacyUpgradeResponse { Result result = 1; enum Result { OK = 0; NOT_FOUND = 1; } - // Ordered from highest to lowest priority - repeated UpgradeableIntent items = 2; + repeated UpgradeableIntent items = 2 ; } - message GetLimitsRequest { // The owner account whose limits will be calculated. Any other owner accounts // linked with the same identity of the owner will also be applied. common.v1.SolanaAccountId owner = 1; - // The signature is of serialize(GetLimitsRequest) without this field set // using the private key of the owner account. This provides an authentication // mechanism to the RPC. common.v1.Signature signature = 2; - // All transactions starting at this time will be incorporated into the consumed // limit calculation. Clients should set this to the start of the current day in // the client's current time zone (because server has no knowledge of this atm). google.protobuf.Timestamp consumed_since = 3; } - message GetLimitsResponse { Result result = 1; enum Result { OK = 0; } - // Send limits keyed by currency map send_limits_by_currency = 2; - // Deposit limits DepositLimit deposit_limit = 3; - // Micro payment limits keyed by currency map micro_payment_limits_by_currency = 4; - // Buy module limits keyed by currency map buy_module_limits_by_currency = 5; } - message GetPaymentHistoryRequest { // The owner account to get payment history for common.v1.SolanaAccountId owner = 1; - // An optional history cursor indicating where in the history to resume from. Cursor cursor = 2; - // The number of results to return per request. Default is 100. uint32 page_size = 3; - // The order in which to return history items from the cursor. Direction direction = 4; enum Direction { // ASC direction returns all history items in ascending order. ASC = 0; - // DESC direction returns all history items in descending order. DESC = 1; } - // The signature is of serialize(GetPaymentHistoryRequest) without this field set // using the private key of the owner account. This provides an authentication // mechanism to the RPC. common.v1.Signature signature = 5; } - message GetPaymentHistoryResponse { Result result = 1; enum Result { OK = 0; NOT_FOUND = 1; } - - repeated PaymentHistoryItem items = 2; + repeated PaymentHistoryItem items = 2 ; } - message CanWithdrawToAccountRequest { - common.v1.SolanaAccountId account = 1; + common.v1.SolanaAccountId account = 1; } - message CanWithdrawToAccountResponse { // Metadata so the client knows how to withdraw to the account. Server cannot // provide precalculated addresses in this response to maintain non-custodial @@ -381,7 +290,6 @@ message CanWithdrawToAccountResponse { TokenAccount = 1; // Client uses the address as is in SubmitIntent OwnerAccount = 2; // Client locally derives the ATA to use in SubmitIntent } - // Server-controlled flag to indicate if the account can be withdrawn to. // There are several reasons server may deny it, including: // - Wrong type of Code account @@ -389,26 +297,21 @@ message CanWithdrawToAccountResponse { // - Unsupported external account type (eg. token account but of the wrong mint) // This is guaranteed to be false when account_type = Unknown. bool is_valid_payment_destination = 1; - // Token account requires initialization before the withdrawal can occur. // Server has chosen not to subsidize the fees. The response is guaranteed // to have set is_valid_payment_destination = false in this case. bool requires_initialization = 3; } - message AirdropRequest { // The type of airdrop to claim - AirdropType airdrop_type = 1; - + AirdropType airdrop_type = 1 ; // The owner account to airdrop Kin to common.v1.SolanaAccountId owner = 2; - // The signature is of serialize(AirdropRequest) without this field set // using the private key of the owner account. This provides an authentication // mechanism to the RPC. common.v1.Signature signature = 3; } - message AirdropResponse { Result result = 1; enum Result { @@ -418,94 +321,72 @@ message AirdropResponse { // The airdrop has already been claimed by the owner ALREADY_CLAIMED = 2; } - // Exchange data for the amount of Kin airdropped when successful ExchangeData exchange_data = 2; } - message SwapRequest { oneof request { - Initiate initiate = 1; SubmitSignature submit_signature = 2; } - message Initiate { // The verified owner account public key common.v1.SolanaAccountId owner = 1; - // The user authority account that will sign to authorize the swap. Ideally, // this is an account derived off the owner account that is solely responsible // for swapping. common.v1.SolanaAccountId swap_authority = 2; - // Maximum amount to swap from the source mint, in quarks. If value is set to zero, // the entire amount will be swapped. uint64 limit = 3; - // Whether the client wants the RPC to wait for blockchain status. If false, // then the RPC will return Success when the swap is submitted to the blockchain. - // Otherwise, the RPC will observe and report back the status of the transaction. + // Otherwise, the RPC will observe and report back the status of the transaction. bool wait_for_blockchain_status = 4; - // The signature is of serialize(Initiate) without this field set using the // private key of the owner account. This provides an authentication mechanism // to the RPC. common.v1.Signature signature = 5; } - message SubmitSignature { // The signature for the locally constructed swap transaction common.v1.Signature signature = 1; } } - message SwapResponse { oneof response { - ServerParameters server_parameters = 1; Success success = 2; Error error = 3; } - message ServerParameters { // Subisdizer account that will be paying for the swap common.v1.SolanaAccountId payer = 1; - // Recent blockhash common.v1.Blockhash recent_blockhash = 2; - // Compute unit limit provided to the ComputeBudget::SetComputeUnitLimit // instruction. If the value is 0, then the instruction can be omitted. uint32 compute_unit_limit = 3; - // Compute unit price provided in the ComputeBudget::SetComputeUnitPrice // instruction. If the value is 0, then the instruction can be omitted. uint64 compute_unit_price = 4; - // On-chain program that will be performing the swap common.v1.SolanaAccountId swap_program = 5; - // Accounts provided to the swap instruction - repeated common.v1.InstructionAccount swap_ixn_accounts = 6; - + repeated common.v1.InstructionAccount swap_ixn_accounts = 6 ; // Instruction data for the swap instruction - bytes swap_ixn_data = 7; - + bytes swap_ixn_data = 7 ; // Maximum quarks that will be sent out of the source account after // executing the swap. If not, the validation instruction will cause // the transaction to fail. uint64 max_to_send = 8; - // Minimum quarks that will be received into the destination account // after executing the swap. If not, the validation instruction will // cause the transaction to fail. uint64 min_to_receive = 9; - // Nonce to use in swap validator state account PDA common.v1.SolanaAccountId nonce = 10; } - message Success { Code code = 1; enum Code { @@ -515,7 +396,6 @@ message SwapResponse { SWAP_FINALIZED = 1; } } - message Error { Code code = 1; enum Code { @@ -528,19 +408,41 @@ message SwapResponse { // The submitted swap transaction failed. Attempt the swap again. SWAP_FAILED = 4; } - repeated ErrorDetails error_details = 2; } } - +message DeclareFiatOnrampPurchaseAttemptRequest { + // The owner account invoking the buy module + common.v1.SolanaAccountId owner = 1; + // The amount being purchased + ExchangeDataWithoutRate purchase_amount = 2; + // A nonce value unique to the purchase. If it's included in a memo for the + // transaction for the deposit to the owner, then purchase_amount will be used + // for display values. Otherwise, the amount will be inferred from the transaction. + common.v1.UUID nonce = 3; + // The signature is of serialize(DeclareFiatOnrampPurchaseAttemptRequest) without + // this field set using the private key of the owner account. This provides an + // authentication mechanism to the RPC. + common.v1.Signature signature = 4; +} +message DeclareFiatOnrampPurchaseAttemptResponse { + Result result = 1; + enum Result { + OK = 0; + // The owner account is not valid (ie. it isn't a Code account) + INVALID_OWNER = 1; + // The currency isn't supported + UNSUPPORTED_CURRENCY = 2; + // The amount specified exceeds limits + AMOUNT_EXCEEDS_MAXIMUM = 3; + } +} // // Metadata definitions // - // Metadata describes the high-level details of an intent message Metadata { oneof type { - OpenAccountsMetadata open_accounts = 1; SendPrivatePaymentMetadata send_private_payment = 2; ReceivePaymentsPrivatelyMetadata receive_payments_privately = 3; @@ -551,7 +453,6 @@ message Metadata { EstablishRelationshipMetadata establish_relationship = 8; } } - // Open a set of accounts. Currently, clients should only use this for new users // to open all required accounts up front (buckets, incoming, and outgoing). // @@ -564,12 +465,11 @@ message Metadata { message OpenAccountsMetadata { // Nothing is currently required } - // Sends a payment to a destination account with initial temporary privacy. Clients // should also reorganize their bucket accounts and rotate their temporary outgoing // account. // -// Action Spec (In Person Cash Payment or Withdrawal or Tio): +// Action Spec (In Person Cash Payment or Withdrawal or Tip): // // actions = [ // // Section 1: Transfer ExchangeData.Quarks from BUCKET_X_KIN accounts to TEMPORARY_OUTGOING account with reogranizations @@ -645,24 +545,18 @@ message OpenAccountsMetadata { message SendPrivatePaymentMetadata { // The destination token account to send funds to common.v1.SolanaAccountId destination = 1; - // The exchange data of total funds being sent to the destination ExchangeData exchange_data = 2; - // Is the payment a withdrawal? For destinations that are not Code temporary // accounts, this must be set to true. bool is_withdrawal = 3; - // Is the payment for a remote send? bool is_remote_send = 4; - // Is the payment for a tip? bool is_tip = 5; - // If is_tip is true, the user being tipped TippedUser tipped_user = 6; } - // Send a payment to a destination account publicly. // // Action Spec: @@ -674,18 +568,14 @@ message SendPublicPaymentMetadata { // account is assumed if this field is not set for backwards compatibility with // old clients. common.v1.SolanaAccountId source = 4; - // The destination token account to send funds to. This cannot be a Code // temporary account. common.v1.SolanaAccountId destination = 1; - // The exchange data of total funds being sent to the destination ExchangeData exchange_data = 2; - // Is the payment a withdrawal? Currently, this is always true. bool is_withdrawal = 3; } - // Receive funds into an organizer with initial temporary privacy. Clients should // also reorganize their bucket accounts and rotate their temporary incoming account // as applicable. Only accounts owned and derived by a user's 12 words should operate @@ -723,16 +613,13 @@ message SendPublicPaymentMetadata { message ReceivePaymentsPrivatelyMetadata { // The temporary incoming, primary or relationship account to receive funds from common.v1.SolanaAccountId source = 1; - // The exact amount of Kin in quarks being received uint64 quarks = 2; - // Is the receipt of funds from a deposit? If true, the source account must // be a primary or relationship account. Otherwise, it must be from a temporary // incoming account. bool is_deposit = 3; } - // Receive funds into a user-owned account publicly. All use cases of this intent // close the account, so all funds must be moved. Use this intent to receive payments // from an account not owned by a user's 12 words into a temporary incoming account, @@ -744,31 +631,25 @@ message ReceivePaymentsPrivatelyMetadata { message ReceivePaymentsPubliclyMetadata { // The remote send gift card to receive funds from common.v1.SolanaAccountId source = 1; - // The exact amount of Kin in quarks being received uint64 quarks = 2; - // Is the receipt of funds from a remote send gift card? Currently, this is // the only use case for this intent and validation enforces the flag to true. bool is_remote_send = 3; - // If is_remote_send is true, is the gift card being voided? The user owner // account's 12 words that issued the gift card may only set this flag to true. // Functionally, this doesn't affect the intent, but rather if we decide to show // it in a user-friendly payment history. bool is_issuer_voiding_gift_card = 4; - // If is_remote_send is true, the original exchange data that was provided as // part of creating the gift card account. This is purely a server-provided value. // SubmitIntent will disallow this being set. ExchangeData exchange_data = 5; } - // Upgrade existing private transactions from temporary to permanent privacy. message UpgradePrivacyMetadata { // Nothing is currently required } - // Migrates existing users prior to the privacy implementation by: // 1. If there are funds in the LEGACY_PRIMARY_2022 account, then move them // to the new PRIMARY account, so the client can later simulate a deposit @@ -790,7 +671,6 @@ message MigrateToPrivacy2022Metadata { // the account is empty. uint64 quarks = 1; } - // Establishes a long-lived private relationship between a user and another // entity. // @@ -801,13 +681,11 @@ message MigrateToPrivacy2022Metadata { // // actions = [OpenAccountAction(RELATIONSHIP)] message EstablishRelationshipMetadata { - common.v1.Relationship relationship = 1; + common.v1.Relationship relationship = 1; } - // // Action Definitions // - // Action is a well-defined, ordered and small set of transactions for a unit of work // that the client wants to perform on the blockchain. Clients provide parameters known // to them in the action. @@ -815,10 +693,8 @@ message Action { // The ID of this action, which is unique within an intent. It must match // the index of the action's location in the SubmitAction's actions field. uint32 id = 1; - // The type of action to perform. oneof type { - OpenAccountAction open_account = 2; CloseEmptyAccountAction close_empty_account = 3; CloseDormantAccountAction close_dormant_account = 4; @@ -830,7 +706,6 @@ message Action { FeePaymentAction fee_payment = 10; } } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -842,27 +717,21 @@ message Action { message OpenAccountAction { // The type of account, which will dictate its intended use common.v1.AccountType account_type = 1; - // The owner of the account. For accounts liked to a user's 12 words, this is // the verified parent owner account public key. All other account types should // set this to the authority value. common.v1.SolanaAccountId owner = 2; - // The index used to for accounts that are derived from owner uint64 index = 3; - // The public key of the private key that has authority over the opened token account common.v1.SolanaAccountId authority = 4; - // The token account being opened common.v1.SolanaAccountId token = 5; - // The signature is of serialize(OpenAccountAction) without this field set // using the private key of the authority account. This provides a proof // of authorization to link authority to owner. common.v1.Signature authority_signature = 6; } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -872,15 +741,12 @@ message OpenAccountAction { message CloseEmptyAccountAction { // The type of account being closed common.v1.AccountType account_type = 1; - // The public key of the private key that has authority over the token account // that should be closed common.v1.SolanaAccountId authority = 2; - // The token account being closed common.v1.SolanaAccountId token = 3; } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -893,18 +759,14 @@ message CloseEmptyAccountAction { message CloseDormantAccountAction { // The type of account being closed common.v1.AccountType account_type = 1; - // The public key of the private key that has authority over the token account // that should be closed common.v1.SolanaAccountId authority = 2; - // The token account being closed common.v1.SolanaAccountId token = 3; - // The destination where funds are withdrawn to common.v1.SolanaAccountId destination = 4 ; } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -914,17 +776,13 @@ message CloseDormantAccountAction { message NoPrivacyTransferAction { // The public key of the private key that has authority over source common.v1.SolanaAccountId authority = 1; - // The source account where funds are transferred from common.v1.SolanaAccountId source = 2; - // The destination account where funds are transferred to common.v1.SolanaAccountId destination = 3; - // The Kin quark amount to transfer uint64 amount = 4; } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -937,22 +795,17 @@ message NoPrivacyTransferAction { message NoPrivacyWithdrawAction { // The public key of the private key that has authority over source common.v1.SolanaAccountId authority = 1; - // The source account where funds are transferred from common.v1.SolanaAccountId source = 2; - // The destination account where funds are transferred to common.v1.SolanaAccountId destination = 3; - // The intended Kin quark amount to withdraw uint64 amount = 4; - + // Whether the account is closed afterwards. This is always true, since there // are no current se cases to leave it open. bool should_close = 5; } - - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -969,17 +822,13 @@ message NoPrivacyWithdrawAction { message TemporaryPrivacyTransferAction { // The public key of the private key that has authority over source common.v1.SolanaAccountId authority = 1; - // The source account where funds are transferred from common.v1.SolanaAccountId source = 2; - // The destination account where funds are transferred to common.v1.SolanaAccountId destination = 3; - - // The Kin quark amount to transfer + // The Kin quark amount to transfer uint64 amount = 4; } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -996,17 +845,13 @@ message TemporaryPrivacyTransferAction { message TemporaryPrivacyExchangeAction { // The public key of the private key that has authority over source common.v1.SolanaAccountId authority = 1; - // The source account where funds are exchanged from common.v1.SolanaAccountId source = 2; - // The destination account where funds are exchanged to common.v1.SolanaAccountId destination = 3; - - // The Kin quark amount to exchange + // The Kin quark amount to exchange uint64 amount = 4; } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -1017,7 +862,6 @@ message PermanentPrivacyUpgradeAction { // The action ID of the temporary private transfer or exchange to upgrade uint32 action_id = 1; } - // Transaction 1 // Instructions: // 1. system::AdvanceNonce @@ -1034,25 +878,19 @@ message FeePaymentAction { CODE = 0; // Hardcoded $0.01 USD fee to a dynamic fee account specified by server THIRD_PARTY = 1; // Third party fee specified at time of payment request } - // The public key of the private key that has authority over source common.v1.SolanaAccountId authority = 1; - // The source account where funds are transferred from common.v1.SolanaAccountId source = 2; - // The Kin quark amount to transfer uint64 amount = 3; - // The destination where the fee payment is being made for fees outside of // Code. common.v1.SolanaAccountId destination = 5; } - // // Server Parameter Definitions // - // ServerParameter are a set of parameters known and returned by server that // enables clients to complete transaction construction. Any necessary proofs, // which are required to be locally verifiable, are also provided to ensure @@ -1060,14 +898,11 @@ message FeePaymentAction { message ServerParameter { // The action the server parameters belong to uint32 action_id = 1; - // The set of nonces used for the action. Server will only provide values // for transactions requiring client signatures. - repeated NoncedTransactionMetadata nonces = 2; - + repeated NoncedTransactionMetadata nonces = 2 ; // The type of server parameter which maps to the type of action requested oneof type { - OpenAccountServerParameter open_account = 3; CloseEmptyAccountServerParameter close_empty_account = 4; CloseDormantAccountServerParameter close_dormant_account = 5; @@ -1079,114 +914,89 @@ message ServerParameter { FeePaymentServerParameter fee_payment = 11; } } - message NoncedTransactionMetadata { // The nonce account to use in the system::AdvanceNonce instruction common.v1.SolanaAccountId nonce = 1; - // The blockhash to set in the transaction common.v1.Blockhash blockhash = 2; } - message OpenAccountServerParameter { // There are no transactions requiring client signatures } - message CloseEmptyAccountServerParameter { // There are no action-specific server parameters } - message CloseDormantAccountServerParameter { - // There are no action-specific server parameters + // There are no action-specific server parameters } - message NoPrivacyTransferServerParameter { // There are no action-specific server parameters } - message NoPrivacyWithdrawServerParameter { // There are no action-specific server parameters } - message TemporaryPrivacyTransferServerParameter { // The treasury that will be used to split payments and provide a level of privacy common.v1.SolanaAccountId treasury = 1; - // A recent root server observed from the treasury common.v1.Hash recent_root = 2; } - message TemporaryPrivacyExchangeServerParameter { // The treasury that will be used to split payments and provide a level of privacy common.v1.SolanaAccountId treasury = 1; - // A recent root server observed from the treasury common.v1.Hash recent_root = 2; } - message PermanentPrivacyUpgradeServerParameter { // The new commitment that is being paid common.v1.SolanaAccountId new_commitment = 1; - // The new commitment account's transcript. This is purely needed by client // to validate merkle_root with commitment PDA logic. common.v1.Hash new_commitment_transcript = 2; - // The new commitment account's destination. This is purely needed by client // to validate merkle_root with commitment PDA logic. common.v1.SolanaAccountId new_commitment_destination = 3; - // The new commitment account's payment amount. This is purely needed by client // to validate merkle_root with commitment PDA logic. uint64 new_commitment_amount = 4; - // The merkle root, which was the recent root used in the new commitment account common.v1.Hash merkle_root = 5; - // The merkle proof that validates the original commitment occurred prior to // the new commitment server is asking client to pay - repeated common.v1.Hash merkle_proof = 6; + repeated common.v1.Hash merkle_proof = 6 ; } - message FeePaymentServerParameter { // The destination account where Code fee payments should be sent. This will // only be set when the corresponding FeePaymentAction Type is CODE. common.v1.SolanaAccountId code_destination = 1; } - // // Structured Error Definitions // - message ErrorDetails { oneof type { ReasonStringErrorDetails reason_string = 1; InvalidSignatureErrorDetails invalid_signature = 2; - IntentDeniedErrorDetails intent_denied = 3; // Set when SubmitIntentResponse.Error.Code = DENIED + DeniedErrorDetails denied = 3; } } - message ReasonStringErrorDetails { // Human readable string indicating the failure. - string reason = 1; + string reason = 1 ; } - message InvalidSignatureErrorDetails { - // The action whose signature mismatched - uint32 action_id = 1; - + // The action whose signature mismatched + uint32 action_id = 1; // The transaction the server expected to have signed. common.v1.Transaction expected_transaction = 2; - // The signature that was provided by the client. common.v1.Signature provided_signature = 3; } - -message IntentDeniedErrorDetails { - Reason reason = 1; - enum Reason { - // Reason not given and is obscured from client - UNKNOWN = 0; +message DeniedErrorDetails { + Code code = 1; + enum Code { + // Reason code not yet defined + UNSPECIFIED = 0; // Phone number has exceeded its free account allocation TOO_MANY_FREE_ACCOUNTS_FOR_PHONE_NUMBER = 1; // Device has exceeded its free account allocation @@ -1197,61 +1007,49 @@ message IntentDeniedErrorDetails { // The device is not supported (eg. it fails device attestation checks) UNSUPPORTED_DEVICE = 4; } + // Human readable string indicating the failure. + string reason = 2 ; } - // // Other Model Definitions // - // UpgradeableIntent is an intent whose actions can be upgraded. message UpgradeableIntent { // The intent ID common.v1.IntentId id = 1; - // The set of private actions that can be upgraded - repeated UpgradeablePrivateAction actions = 2; - + repeated UpgradeablePrivateAction actions = 2 ; message UpgradeablePrivateAction { // The transaction blob that was signed by the client. Clients *MUST* use // the source and destination account in the timelock::TransferWithAuthority // instruction to validate all fields provided by server by locally computing // the expected addresses. common.v1.Transaction transaction_blob = 1; - // The client's signature for the transaction. Clients MUST use this to // locally validate the transaction blob provided by server. common.v1.Signature client_signature = 2; - // The action ID of this transaction uint32 action_id = 3; - // The source account's type, which hints how to efficiently derive source common.v1.AccountType source_account_type = 4; - +; // The source account's derivation index, which hints how to efficiently derive source uint64 source_derivation_index = 5; - // The original destination account that was paid by the treasury common.v1.SolanaAccountId original_destination = 6; - // The original quark amount for the action uint64 original_amount = 7; - // The treasury used for this the private action common.v1.SolanaAccountId treasury = 8; - // The recent root observed at the time of intent creation for this private action common.v1.Hash recent_root = 9; } } - message PaymentHistoryItem { // The cursor position of this item. Cursor cursor = 1; - // Exchange data related to the payment ExchangeData exchange_data = 2; - // Is this payment a send or receive? PaymentType payment_type = 3; enum PaymentType { @@ -1259,82 +1057,61 @@ message PaymentHistoryItem { SEND = 1; RECEIVE = 2; } - // If the payment was a SEND, was it a withdraw? bool is_withdraw = 4; - // If the payment was a RECEIVE, was it a deposit? bool is_deposit = 5; - // The timestamp of the payment google.protobuf.Timestamp timestamp = 6; - // Was the payment involved in a remote send? bool is_remote_send = 7; - // If payment_type is RECEIVE and is_remote_send is true, was the funds being // returned back to the issuer? bool is_returned = 8; - // If payment_type is RECEIVE, is this receive an airdrop part of a reward, incentive, etc.? bool is_airdrop = 9; - // If is_airdrop is true, the type of airdrop received. AirdropType airdrop_type = 10; - - // Is this a micro payment? + // Is this a micro payment? bool is_micro_payment = 11; - // The intent ID associated with this history item common.v1.IntentId intent_id = 12; } - // ExchangeData defines an amount of Kin with currency exchange data message ExchangeData { // ISO 4217 alpha-3 currency code. string currency = 1; - // The agreed upon exchange rate. This might not be the same as the // actual exchange rate at the time of intent or fund transfer. double exchange_rate = 2; - // The agreed upon transfer amount in the currency the payment was made // in. double native_amount = 3; - // The exact amount of quarks to send. This will be used as the source of // truth for validating transaction transfer amounts. uint64 quarks = 4; } - message ExchangeDataWithoutRate { // ISO 4217 alpha-3 currency code. string currency = 1; - // The agreed upon transfer amount in the currency the payment was made // in. double native_amount = 2; } - message AdditionalFeePayment { // Destination Kin token account where the fee payment will be made common.v1.SolanaAccountId destination = 1; - // Fee percentage, in basis points, of the total quark amount of a payment. - uint32 fee_bps = 2; + uint32 fee_bps = 2 ; } - message SendLimit { // Remaining limit to apply on the next transaction float next_transaction = 1; - // Maximum allowed on a per-transaction basis float max_per_transaction = 2; - // Maximum allowed on a per-day basis float max_per_day = 3; } - message DepositLimit { // Maximum quarks that may be deposited at any time. Server will guarantee // this threshold will be below enforced dollar value limits, while also @@ -1342,42 +1119,33 @@ message DepositLimit { // max payment sends. Total dollar value limits may be spread across many deposits. uint64 max_quarks = 1; } - message MicroPaymentLimit { // Maximum native amount that can be applied per micro payment transaction float max_per_transaction = 1; - // Minimum native amount that can be applied per micro payment transaction float min_per_transaction = 2; } - message BuyModuleLimit { // Minimum amount that can be purchased through the buy module float min_per_transaction = 1; - // Maximum amount that can be purchased through the buy module float max_per_transaction = 2; } - message TippedUser { - Platform platform = 1; + Platform platform = 1 ; enum Platform { UNKNOWN = 0; TWITTER = 1; } - - string username = 2; + string username = 2 ; } - - message Cursor { - bytes value = 1; + bytes value = 1 ; } - enum AirdropType { UNKNOWN = 0; // Reward for giving someone else their first Kin GIVE_FIRST_KIN = 1; // Airdrop for getting a user started with first Kin balance GET_FIRST_KIN = 2; -} \ No newline at end of file +} diff --git a/service/protos/src/main/proto/user/v1/identity_service.proto b/service/protos/src/main/proto/user/v1/identity_service.proto index 8f21b7bcf..db3574b6f 100644 --- a/service/protos/src/main/proto/user/v1/identity_service.proto +++ b/service/protos/src/main/proto/user/v1/identity_service.proto @@ -52,7 +52,6 @@ service Identity { // information. rpc GetTwitterUser(GetTwitterUserRequest) returns (GetTwitterUserResponse); } - message LinkAccountRequest { // The public key of the owner account that will be linked to a user. common.v1.SolanaAccountId owner_account_id = 1; @@ -66,9 +65,7 @@ message LinkAccountRequest { // SMS code using the phone verification service. phone.v1.PhoneLinkingToken phone = 3; } - } - message LinkAccountResponse { Result result = 1; enum Result { @@ -81,7 +78,6 @@ message LinkAccountResponse { // retry at a later time. RATE_LIMITED = 2; } - // The user that was linked to the owner account User user = 2; // The data container where the user can store a copy of their data @@ -93,9 +89,7 @@ message LinkAccountResponse { // Metadata that corresponds to a phone-based identifying feature. PhoneMetadata phone = 5; } - } - message UnlinkAccountRequest { // The public key of the owner account that will be unliked. common.v1.SolanaAccountId owner_account_id = 1; @@ -107,9 +101,7 @@ message UnlinkAccountRequest { // The phone number associated with the owner account. common.v1.PhoneNumber phone_number = 4; } - } - message UnlinkAccountResponse { Result result = 1; enum Result { @@ -118,9 +110,7 @@ message UnlinkAccountResponse { // that never had a valid association. NEVER_ASSOCIATED = 1; } - } - message GetUserRequest { // The public key of the owner account that signed this request message. common.v1.SolanaAccountId owner_account_id = 1; @@ -132,9 +122,7 @@ message GetUserRequest { oneof identifying_feature { common.v1.PhoneNumber phone_number = 3; } - } - message GetUserResponse { Result result = 1; enum Result { @@ -146,7 +134,6 @@ message GetUserResponse { // The user exists, but at least one of their timelock accounts is unlocked UNLOCKED_TIMELOCK_ACCOUNT = 3; } - // The user associated with the identifier User user = 2; // The data container where the user can store a copy of their data @@ -158,27 +145,21 @@ message GetUserResponse { // Metadata that corresponds to a phone-based identifying feature. PhoneMetadata phone = 5; } - // Whether client internal flags are enabled for this user bool enable_internal_flags = 6; // Set of which airdrops the user is eligible to receive repeated transaction.v2.AirdropType eligible_airdrops = 7; - // Wether the buy module is enabled for this user bool enable_buy_module = 8; } - message UpdatePreferencesRequest { // The public key of the owner account that signed this request message. common.v1.SolanaAccountId owner_account_id = 1; - // The data container for the copy of the contact list being added to. common.v1.DataContainerId container_id = 2; - // The signature is of serialize(UpdatePreferencesRequest) without this field set // using the private key of owner_account_id. common.v1.Signature signature = 3; - // The user's locale, which is used for server-side localization of things like // chat messages, pushes, etc. If no locale is set, or the provided locale isn't // supported, then English is used as the default fallback. @@ -188,17 +169,14 @@ message UpdatePreferencesRequest { // are updated. common.v1.Locale locale = 4; } - message UpdatePreferencesResponse { Result result = 1; enum Result { OK = 0; - // The provided locale couldn't be parsed or recognized and is invalid. INVALID_LOCALE = 1; } } - message LoginToThirdPartyAppRequest { // The intent ID identifying the instance of the login flow. common.v1.IntentId intent_id = 1; @@ -208,7 +186,6 @@ message LoginToThirdPartyAppRequest { // the user. common.v1.Signature signature = 3; } - message LoginToThirdPartyAppResponse { Result result = 1; enum Result { @@ -227,9 +204,7 @@ message LoginToThirdPartyAppResponse { // account with the correct identifier specified in the original request. INVALID_ACCOUNT = 5; } - } - message GetLoginForThirdPartyAppRequest { // The intent ID identifying the instance of the login flow. common.v1.IntentId intent_id = 1; @@ -239,7 +214,6 @@ message GetLoginForThirdPartyAppRequest { // to domain verification, authenticates the third party. common.v1.Signature signature = 3; } - message GetLoginForThirdPartyAppResponse { Result result = 1; enum Result { @@ -252,17 +226,13 @@ message GetLoginForThirdPartyAppResponse { // logged in user yet. NO_USER_LOGGED_IN = 3; } - // The relationship authority account that logged in. common.v1.SolanaAccountId user_id = 2; } - - message GetTwitterUserRequest { oneof query { // The Twitter username to query against - string username = 1; - + string username = 1 ; // The tip address to query against common.v1.SolanaAccountId tip_address = 2; } @@ -274,10 +244,8 @@ message GetTwitterUserResponse { // The Twitter user doesn't exist or isn't linked with a Code account NOT_FOUND = 1; } - TwitterUser twitter_user = 2; } - // User is the highest order of a form of identity within Code. // // Note: Users outside Code are modelled as relationship accounts @@ -287,7 +255,6 @@ message User { // The identifying features that are associated with the user View view = 2; } - // View is a well-defined set of identifying features. It is contrained to having // exactly one feature set at a time, for now. message View { @@ -297,7 +264,6 @@ message View { // supported to date. common.v1.PhoneNumber phone_number = 1; } - message PhoneMetadata { // State that determines whether a phone number is linked to the owner // account. A phone number is linked if we can treat it as an alias. @@ -305,20 +271,15 @@ message PhoneMetadata { // of whether the number was linked at any point in time. bool is_linked = 1; } - message TwitterUser { // Public key for a token account where tips are routed common.v1.SolanaAccountId tip_address = 1; - // The user's username on Twitter - string username = 2; - + string username = 2 ; // The user's friendly name on Twitter - string name = 3; - + string name = 3 ; // URL to the user's Twitter profile picture - string profile_pic_url = 4; - + string profile_pic_url = 4 ; // The type of Twitter verification associated with the user VerifiedType verified_type = 5; enum VerifiedType { @@ -327,7 +288,6 @@ message TwitterUser { BUSINESS = 2; GOVERNMENT = 3; } - // The number of followers the user has on Twitter - uint32 follower_count = 6; + uint32 follower_count = 6; }