Skip to content

Commit

Permalink
feat: share and parse transaction deep link
Browse files Browse the repository at this point in the history
  • Loading branch information
Cuteivist committed Oct 14, 2024
1 parent 86cd41d commit f234a94
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 7 deletions.
99 changes: 94 additions & 5 deletions protocol/messenger_share_urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,21 @@ type ContactURLData struct {
PublicKey string `json:"publicKey"`
}

type TransactionURLData struct {
TxType int `json:"txType"`
Address string `json:"address"`
Amount string `json:"amount"`
Asset string `json:"asset"`
ChainID int `json:"chainId"`
ToAsset string `json:"toAsset"`
}

type URLDataResponse struct {
Community *CommunityURLData `json:"community"`
Channel *CommunityChannelURLData `json:"channel"`
Contact *ContactURLData `json:"contact"`
Shard *shard.Shard `json:"shard,omitempty"`
Community *CommunityURLData `json:"community"`
Channel *CommunityChannelURLData `json:"channel"`
Contact *ContactURLData `json:"contact"`
Transaction *TransactionURLData `json:"tx"`
Shard *shard.Shard `json:"shard,omitempty"`
}

const baseShareURL = "https://status.app"
Expand All @@ -58,12 +68,14 @@ const userWithDataPath = "u/"
const communityPath = "c#"
const communityWithDataPath = "c/"
const channelPath = "cc/"
const transactionPath = "tx/"

const sharedURLUserPrefix = baseShareURL + "/" + userPath
const sharedURLUserPrefixWithData = baseShareURL + "/" + userWithDataPath
const sharedURLCommunityPrefix = baseShareURL + "/" + communityPath
const sharedURLCommunityPrefixWithData = baseShareURL + "/" + communityWithDataPath
const sharedURLChannelPrefixWithData = baseShareURL + "/" + channelPath
const sharedURLTransaction = baseShareURL + "/" + transactionPath

const channelUUIDRegExp = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$"

Expand Down Expand Up @@ -302,6 +314,77 @@ func (m *Messenger) prepareEncodedCommunityChannelData(community *communities.Co
return encodedData, shortKey, nil
}

func (m *Messenger) ShareTransactionURL(request *requests.TransactionShareURL) (string, error) {
encodedData, err := m.prepareTransactionUrl(request)
if err != nil {
return "", err
}
return fmt.Sprintf("%s%s", sharedURLTransaction, encodedData), nil
}

func (m *Messenger) prepareTransactionUrl(request *requests.TransactionShareURL) (string, error) {
if err := request.Validate(); err != nil {
return "", err
}

txProto := &protobuf.Transaction{
TxType: uint32(request.TxType),
Address: request.Address,
Amount: request.Amount,
Asset: request.Asset,
ChainId: uint32(request.ChainID),
ToAsset: request.ToAsset,
}
txData, err := proto.Marshal(txProto)
if err != nil {
return "", err
}
urlDataProto := &protobuf.URLData{
Content: txData,
}

urlData, err := proto.Marshal(urlDataProto)
if err != nil {
return "", err
}

encodedData, err := encodeDataURL(urlData)
if err != nil {
return "", err
}
return encodedData, nil
}

func parseTransactionURL(data string) (*URLDataResponse, error) {
urlData, err := decodeDataURL(data)
if err != nil {
return nil, err
}

var urlDataProto protobuf.URLData
err = proto.Unmarshal(urlData, &urlDataProto)
if err != nil {
return nil, err
}

var txProto protobuf.Transaction
err = proto.Unmarshal(urlDataProto.Content, &txProto)
if err != nil {
return nil, err
}

return &URLDataResponse{
Transaction: &TransactionURLData{
TxType: int(txProto.TxType),
Address: txProto.Address,
Amount: txProto.Amount,
Asset: txProto.Asset,
ChainID: int(txProto.ChainId),
ToAsset: txProto.ToAsset,
},
}, nil
}

func (m *Messenger) ShareCommunityChannelURLWithData(request *requests.CommunityChannelShareURL) (string, error) {
if err := request.Validate(); err != nil {
return "", err
Expand Down Expand Up @@ -518,7 +601,8 @@ func IsStatusSharedURL(url string) bool {
strings.HasPrefix(url, sharedURLUserPrefixWithData) ||
strings.HasPrefix(url, sharedURLCommunityPrefix) ||
strings.HasPrefix(url, sharedURLCommunityPrefixWithData) ||
strings.HasPrefix(url, sharedURLChannelPrefixWithData)
strings.HasPrefix(url, sharedURLChannelPrefixWithData) ||
strings.HasPrefix(url, sharedURLTransaction)
}

func splitSharedURLData(data string) (string, string, error) {
Expand Down Expand Up @@ -576,6 +660,11 @@ func ParseSharedURL(url string) (*URLDataResponse, error) {
return parseCommunityChannelURLWithData(encodedData, chatKey)
}

if strings.HasPrefix(url, sharedURLTransaction) {
trimmedURL := strings.TrimPrefix(url, sharedURLTransaction)
return parseTransactionURL(trimmedURL)
}

return nil, fmt.Errorf("not a status shared url")
}

Expand Down
54 changes: 54 additions & 0 deletions protocol/messenger_share_urls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,3 +497,57 @@ func (s *MessengerShareUrlsSuite) TestShareAndParseUserURLWithData() {
s.Require().Equal(contact.DisplayName, urlData.Contact.DisplayName)
s.Require().Equal(shortKey, urlData.Contact.PublicKey)
}

func (s *MessengerShareUrlsSuite) TestShareTransactionURL() {
request := &requests.TransactionShareURL{
TxType: 0,
Address: "0x1234567890abcdef",
Amount: "0.123",
Asset: "ETH",
ChainID: 123,
ToAsset: "SNT",
}
url, err := s.m.ShareTransactionURL(request)
s.Require().NoError(err)
s.Require().NotEmpty(url)

data, err := s.m.prepareTransactionUrl(request)
s.Require().NoError(err)

expectedURL := fmt.Sprintf("%s/tx/%s", baseShareURL, data)
s.Require().Equal(expectedURL, url)
}

func (s *MessengerShareUrlsSuite) TestShareTransactionURLInvalid() {
request := &requests.TransactionShareURL{
TxType: -1,
}
_, err := s.m.ShareTransactionURL(request)
s.Require().Error(err)
_, err = s.m.prepareTransactionUrl(request)
s.Require().Error(err)
}

func (s *MessengerShareUrlsSuite) TestShareAndParseTransactionURL() {
request := &requests.TransactionShareURL{
TxType: 0,
Address: "0x1234567890abcdef",
Amount: "0.123",
Asset: "ETH",
ChainID: 123,
ToAsset: "SNT",
}
url, err := s.m.ShareTransactionURL(request)
s.Require().NoError(err)

urlData, err := ParseSharedURL(url)
s.Require().NoError(err)
s.Require().NotNil(urlData)

s.Require().Equal(request.TxType, urlData.Transaction.TxType)
s.Require().Equal(request.Address, urlData.Transaction.Address)
s.Require().Equal(request.Amount, urlData.Transaction.Amount)
s.Require().Equal(request.Asset, urlData.Transaction.Asset)
s.Require().Equal(request.ChainID, urlData.Transaction.ChainID)
s.Require().Equal(request.ToAsset, urlData.Transaction.ToAsset)
}
13 changes: 11 additions & 2 deletions protocol/protobuf/url_data.proto
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,17 @@ message User {
string color = 3;
}

message Transaction {
uint32 txType = 1;
string address = 2;
string amount = 3;
string asset = 4;
uint32 chainId = 5;
string toAsset = 6;
}

message URLData {
// Community, Channel, or User
// Community, Channel, User or Transaction
bytes content = 1;
Shard shard = 2;
}
}
26 changes: 26 additions & 0 deletions protocol/requests/transaction_share_url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package requests

import (
"errors"
)

var (
ErrInvalidTransactionType = errors.New("transaction-share-url: invalid transaction type")
)

type TransactionShareURL struct {
TxType int `json:"txType"`
Asset string `json:"asset"`
Amount string `json:"amount"`
Address string `json:"address"`
ChainID int `json:"chainId"`
ToAsset string `json:"toAsset"`
}

func (r *TransactionShareURL) Validate() error {
if r.TxType < 0 {
return ErrInvalidTransactionType
}

return nil
}
4 changes: 4 additions & 0 deletions services/ext/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,10 @@ func (api *PublicAPI) ShareUserURLWithData(pubKey string) (string, error) {
return api.service.messenger.ShareUserURLWithData(pubKey)
}

func (api *PublicAPI) ShareTransactionURL(txData *requests.TransactionShareURL) (string, error) {
return api.service.messenger.ShareTransactionURL(txData)
}

func (api *PublicAPI) ParseSharedURL(url string) (*protocol.URLDataResponse, error) {
return protocol.ParseSharedURL(url)
}
Expand Down

0 comments on commit f234a94

Please sign in to comment.