Skip to content

Commit 942d232

Browse files
committed
Incorporate fees into exchange data chat messages
1 parent 8039f50 commit 942d232

File tree

6 files changed

+79
-29
lines changed

6 files changed

+79
-29
lines changed

pkg/code/async/geyser/external_deposit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ func processPotentialExternalDeposit(ctx context.Context, data code_data.Provide
265265
if err != nil {
266266
return errors.Wrap(err, "error updating cash transactions chat")
267267
}
268-
_, err = chat_util.SendMerchantExchangeMessage(ctx, data, intentRecord)
268+
_, err = chat_util.SendMerchantExchangeMessage(ctx, data, intentRecord, nil)
269269
if err != nil {
270270
return errors.Wrap(err, "error updating merchant chat")
271271
}

pkg/code/chat/message_merchant.go

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import (
88

99
chatpb "github.com/code-payments/code-protobuf-api/generated/go/chat/v1"
1010
commonpb "github.com/code-payments/code-protobuf-api/generated/go/common/v1"
11+
transactionpb "github.com/code-payments/code-protobuf-api/generated/go/transaction/v2"
1112

1213
"github.com/code-payments/code-server/pkg/code/common"
1314
code_data "github.com/code-payments/code-server/pkg/code/data"
15+
"github.com/code-payments/code-server/pkg/code/data/action"
1416
"github.com/code-payments/code-server/pkg/code/data/chat"
1517
"github.com/code-payments/code-server/pkg/code/data/intent"
1618
)
@@ -27,7 +29,7 @@ type MessageWithOwner struct {
2729
// that should be pushed are returned.
2830
//
2931
// Note: Tests covered in SubmitIntent history tests
30-
func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, intentRecord *intent.Record) ([]*MessageWithOwner, error) {
32+
func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, intentRecord *intent.Record, actionRecords []*action.Record) ([]*MessageWithOwner, error) {
3133
messageId := intentRecord.IntentId
3234

3335
// There are three possible chats for a merchant:
@@ -47,8 +49,13 @@ func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, i
4749
if !ok {
4850
return nil, nil
4951
}
52+
exchangeDataMinusFees := getExchangeDataMinusFees(exchangeData, intentRecord, actionRecords)
5053

51-
verbByMessageReceiver := make(map[string]chatpb.ExchangeDataContent_Verb)
54+
type verbAndExchangeData struct {
55+
verb chatpb.ExchangeDataContent_Verb
56+
exchangeData *transactionpb.ExchangeData
57+
}
58+
verbAndExchangeDataByMessageReceiver := make(map[string]*verbAndExchangeData)
5259
switch intentRecord.IntentType {
5360
case intent.SendPrivatePayment:
5461
if intentRecord.SendPrivatePaymentMetadata.IsMicroPayment {
@@ -63,9 +70,15 @@ func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, i
6370
isVerifiedChat = paymentRequestRecord.IsVerified
6471
}
6572

66-
verbByMessageReceiver[intentRecord.InitiatorOwnerAccount] = chatpb.ExchangeDataContent_SPENT
73+
verbAndExchangeDataByMessageReceiver[intentRecord.InitiatorOwnerAccount] = &verbAndExchangeData{
74+
verb: chatpb.ExchangeDataContent_SPENT,
75+
exchangeData: exchangeData,
76+
}
6777
if len(intentRecord.SendPrivatePaymentMetadata.DestinationOwnerAccount) > 0 {
68-
verbByMessageReceiver[intentRecord.SendPrivatePaymentMetadata.DestinationOwnerAccount] = chatpb.ExchangeDataContent_RECEIVED
78+
verbAndExchangeDataByMessageReceiver[intentRecord.SendPrivatePaymentMetadata.DestinationOwnerAccount] = &verbAndExchangeData{
79+
verb: chatpb.ExchangeDataContent_RECEIVED,
80+
exchangeData: exchangeDataMinusFees,
81+
}
6982
}
7083
} else if intentRecord.SendPrivatePaymentMetadata.IsWithdrawal {
7184
if len(intentRecord.SendPrivatePaymentMetadata.DestinationOwnerAccount) > 0 {
@@ -79,7 +92,10 @@ func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, i
7992
chatTitle = *destinationAccountInfoRecord.RelationshipTo
8093
chatType = chat.ChatTypeExternalApp
8194
isVerifiedChat = true
82-
verbByMessageReceiver[intentRecord.SendPrivatePaymentMetadata.DestinationOwnerAccount] = chatpb.ExchangeDataContent_RECEIVED
95+
verbAndExchangeDataByMessageReceiver[intentRecord.SendPrivatePaymentMetadata.DestinationOwnerAccount] = &verbAndExchangeData{
96+
verb: chatpb.ExchangeDataContent_RECEIVED,
97+
exchangeData: exchangeData,
98+
}
8399
}
84100
}
85101
}
@@ -96,7 +112,10 @@ func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, i
96112
chatTitle = *destinationAccountInfoRecord.RelationshipTo
97113
chatType = chat.ChatTypeExternalApp
98114
isVerifiedChat = true
99-
verbByMessageReceiver[intentRecord.SendPublicPaymentMetadata.DestinationOwnerAccount] = chatpb.ExchangeDataContent_RECEIVED
115+
verbAndExchangeDataByMessageReceiver[intentRecord.SendPublicPaymentMetadata.DestinationOwnerAccount] = &verbAndExchangeData{
116+
verb: chatpb.ExchangeDataContent_RECEIVED,
117+
exchangeData: exchangeData,
118+
}
100119
}
101120
}
102121
}
@@ -112,14 +131,17 @@ func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, i
112131
chatTitle = *destinationAccountInfoRecord.RelationshipTo
113132
chatType = chat.ChatTypeExternalApp
114133
isVerifiedChat = true
115-
verbByMessageReceiver[intentRecord.ExternalDepositMetadata.DestinationOwnerAccount] = chatpb.ExchangeDataContent_RECEIVED
134+
verbAndExchangeDataByMessageReceiver[intentRecord.ExternalDepositMetadata.DestinationOwnerAccount] = &verbAndExchangeData{
135+
verb: chatpb.ExchangeDataContent_RECEIVED,
136+
exchangeData: exchangeData,
137+
}
116138
}
117139
default:
118140
return nil, nil
119141
}
120142

121143
var messagesToPush []*MessageWithOwner
122-
for account, verb := range verbByMessageReceiver {
144+
for account, verbAndExchangeData := range verbAndExchangeDataByMessageReceiver {
123145
receiver, err := common.NewAccountFromPublicKeyString(account)
124146
if err != nil {
125147
return nil, err
@@ -129,9 +151,9 @@ func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, i
129151
{
130152
Type: &chatpb.Content_ExchangeData{
131153
ExchangeData: &chatpb.ExchangeDataContent{
132-
Verb: verb,
154+
Verb: verbAndExchangeData.verb,
133155
ExchangeData: &chatpb.ExchangeDataContent_Exact{
134-
Exact: exchangeData,
156+
Exact: verbAndExchangeData.exchangeData,
135157
},
136158
},
137159
},
@@ -150,7 +172,7 @@ func SendMerchantExchangeMessage(ctx context.Context, data code_data.Provider, i
150172
isVerifiedChat,
151173
receiver,
152174
protoMessage,
153-
verb != chatpb.ExchangeDataContent_RECEIVED || !isVerifiedChat,
175+
verbAndExchangeData.verb != chatpb.ExchangeDataContent_RECEIVED || !isVerifiedChat,
154176
)
155177
if err != nil && err != chat.ErrMessageAlreadyExists {
156178
return nil, errors.Wrap(err, "error persisting chat message")

pkg/code/chat/util.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
package chat
22

33
import (
4-
"crypto/rand"
54
"time"
65

76
"github.com/mr-tron/base58/base58"
87
"github.com/pkg/errors"
8+
"google.golang.org/protobuf/proto"
99
"google.golang.org/protobuf/types/known/timestamppb"
1010

1111
chatpb "github.com/code-payments/code-protobuf-api/generated/go/chat/v1"
1212
transactionpb "github.com/code-payments/code-protobuf-api/generated/go/transaction/v2"
1313

14+
"github.com/code-payments/code-server/pkg/code/data/action"
15+
"github.com/code-payments/code-server/pkg/code/data/intent"
1416
currency_lib "github.com/code-payments/code-server/pkg/currency"
1517
"github.com/code-payments/code-server/pkg/kin"
16-
"github.com/code-payments/code-server/pkg/code/data/intent"
1718
)
1819

1920
func newProtoChatMessage(
@@ -95,8 +96,35 @@ func getExchangeDataFromIntent(intentRecord *intent.Record) (*transactionpb.Exch
9596
return nil, false
9697
}
9798

98-
func randomMessageId() string {
99-
buffer := make([]byte, 32)
100-
rand.Read(buffer)
101-
return base58.Encode(buffer)
99+
func getExchangeDataMinusFees(exchangeData *transactionpb.ExchangeData, intentRecord *intent.Record, actionRecords []*action.Record) *transactionpb.ExchangeData {
100+
cloned := proto.Clone(exchangeData).(*transactionpb.ExchangeData)
101+
102+
if intentRecord.IntentType != intent.SendPrivatePayment {
103+
return cloned
104+
}
105+
106+
if !intentRecord.SendPrivatePaymentMetadata.IsMicroPayment {
107+
return cloned
108+
}
109+
110+
var thirdPartyPaymentAction *action.Record
111+
for _, actionRecord := range actionRecords {
112+
if actionRecord.ActionType != action.NoPrivacyWithdraw {
113+
continue
114+
}
115+
116+
if *actionRecord.Destination == intentRecord.SendPrivatePaymentMetadata.DestinationTokenAccount {
117+
thirdPartyPaymentAction = actionRecord
118+
break
119+
}
120+
}
121+
122+
// Should never happen
123+
if thirdPartyPaymentAction == nil {
124+
return cloned
125+
}
126+
127+
cloned.Quarks = *thirdPartyPaymentAction.Quantity
128+
cloned.NativeAmount = cloned.ExchangeRate * float64(cloned.Quarks) / float64(kin.QuarksPerKin)
129+
return cloned
102130
}

pkg/code/server/grpc/transaction/v2/history_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,12 @@ func TestPaymentHistory_HappyPath(t *testing.T) {
104104
sendingPhone.conf.simulatePaymentRequest = true
105105

106106
// [Verified Merchant] sendingPhone SPENT $77.7 USD of Kin
107-
// [Verified Merchant] receivingPhone RECEIVED $77.7 USD of Kin
107+
// [Verified Merchant] receivingPhone RECEIVED $77.69 USD of Kin
108108
sendingPhone.privatelyWithdraw777KinToCodeUser(t, receivingPhone).requireSuccess(t)
109109
receivingPhone.deposit777KinIntoOrganizer(t).requireSuccess(t)
110110

111111
// [Verified Merchant] sendingPhone SPENT $32.1 USD of Kin
112-
// [Verified Merchant] receivingPhone RECEIVED $32.1 USD of Kin
112+
// [Verified Merchant] receivingPhone RECEIVED $32.09 USD of Kin
113113
sendingPhone.privatelyWithdraw321KinToCodeUserRelationshipAccount(t, receivingPhone, merchantDomain).requireSuccess(t)
114114

115115
// [Verified Merchant] sendingPhone SPENT 123 Kin
@@ -119,7 +119,7 @@ func TestPaymentHistory_HappyPath(t *testing.T) {
119119
receivingPhone.conf.simulatePaymentRequest = true
120120
receivingPhone.conf.simulateUnverifiedPaymentRequest = true
121121

122-
// [Unverified Mechant] receivingPhone RECEIVED $77.7 USD of Kin
122+
// [Unverified Mechant] receivingPhone RECEIVED $77.69 USD of Kin
123123
receivingPhone.privatelyWithdraw777KinToCodeUser(t, receivingPhone).requireSuccess(t)
124124

125125
sendingPhone.resetConfig()
@@ -342,17 +342,17 @@ func TestPaymentHistory_HappyPath(t *testing.T) {
342342
assert.Equal(t, chatpb.ExchangeDataContent_RECEIVED, protoChatMessage.Content[0].GetExchangeData().Verb)
343343
assert.EqualValues(t, currency_lib.USD, protoChatMessage.Content[0].GetExchangeData().GetExact().Currency)
344344
assert.Equal(t, 0.1, protoChatMessage.Content[0].GetExchangeData().GetExact().ExchangeRate)
345-
assert.Equal(t, 77.7, protoChatMessage.Content[0].GetExchangeData().GetExact().NativeAmount)
346-
assert.Equal(t, kin.ToQuarks(777), protoChatMessage.Content[0].GetExchangeData().GetExact().Quarks)
345+
assert.Equal(t, 77.69, protoChatMessage.Content[0].GetExchangeData().GetExact().NativeAmount)
346+
assert.EqualValues(t, 77690000, protoChatMessage.Content[0].GetExchangeData().GetExact().Quarks)
347347

348348
protoChatMessage = getProtoChatMessage(t, chatMessageRecords[1])
349349
require.Len(t, protoChatMessage.Content, 1)
350350
require.NotNil(t, protoChatMessage.Content[0].GetExchangeData())
351351
assert.Equal(t, chatpb.ExchangeDataContent_RECEIVED, protoChatMessage.Content[0].GetExchangeData().Verb)
352352
assert.EqualValues(t, currency_lib.USD, protoChatMessage.Content[0].GetExchangeData().GetExact().Currency)
353353
assert.Equal(t, 0.1, protoChatMessage.Content[0].GetExchangeData().GetExact().ExchangeRate)
354-
assert.Equal(t, 32.1, protoChatMessage.Content[0].GetExchangeData().GetExact().NativeAmount)
355-
assert.Equal(t, kin.ToQuarks(321), protoChatMessage.Content[0].GetExchangeData().GetExact().Quarks)
354+
assert.Equal(t, 32.09, protoChatMessage.Content[0].GetExchangeData().GetExact().NativeAmount)
355+
assert.EqualValues(t, 32090000, protoChatMessage.Content[0].GetExchangeData().GetExact().Quarks)
356356

357357
protoChatMessage = getProtoChatMessage(t, chatMessageRecords[2])
358358
require.Len(t, protoChatMessage.Content, 1)
@@ -391,8 +391,8 @@ func TestPaymentHistory_HappyPath(t *testing.T) {
391391
assert.Equal(t, chatpb.ExchangeDataContent_RECEIVED, protoChatMessage.Content[0].GetExchangeData().Verb)
392392
assert.EqualValues(t, currency_lib.USD, protoChatMessage.Content[0].GetExchangeData().GetExact().Currency)
393393
assert.Equal(t, 0.1, protoChatMessage.Content[0].GetExchangeData().GetExact().ExchangeRate)
394-
assert.Equal(t, 77.7, protoChatMessage.Content[0].GetExchangeData().GetExact().NativeAmount)
395-
assert.Equal(t, kin.ToQuarks(777), protoChatMessage.Content[0].GetExchangeData().GetExact().Quarks)
394+
assert.Equal(t, 77.69, protoChatMessage.Content[0].GetExchangeData().GetExact().NativeAmount)
395+
assert.EqualValues(t, 77690000, protoChatMessage.Content[0].GetExchangeData().GetExact().Quarks)
396396

397397
//
398398
// Legacy GetPaymentHistory RPC assertions below

pkg/code/server/grpc/transaction/v2/intent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ func (s *transactionServer) SubmitIntent(streamer transactionpb.Transaction_Subm
887887
log.WithError(err).Warn("failure updating cash transaction chat")
888888
return err
889889
}
890-
chatMessagesToPush, err = chat_util.SendMerchantExchangeMessage(ctx, s.data, intentRecord)
890+
chatMessagesToPush, err = chat_util.SendMerchantExchangeMessage(ctx, s.data, intentRecord, actionRecords)
891891
if err != nil {
892892
log.WithError(err).Warn("failure updating merchant chat")
893893
return err

pkg/code/server/grpc/transaction/v2/testutil.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ func (s *serverTestEnv) simulateExternalDepositHistoryItem(t *testing.T, owner,
374374
require.NoError(t, s.data.SaveIntent(s.ctx, intentRecord))
375375

376376
require.NoError(t, chat_util.SendCashTransactionsExchangeMessage(s.ctx, s.data, intentRecord))
377-
_, err := chat_util.SendMerchantExchangeMessage(s.ctx, s.data, intentRecord)
377+
_, err := chat_util.SendMerchantExchangeMessage(s.ctx, s.data, intentRecord, nil)
378378
require.NoError(t, err)
379379
}
380380

0 commit comments

Comments
 (0)