Skip to content

Task/andrin/str 354 #115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pkg/model/request.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package model

import (
"database/sql"
"time"

"github.com/jmoiron/sqlx/types"
Expand Down Expand Up @@ -32,6 +33,17 @@ type TransactionUpdates struct {
StringFee *string `json:"stringFee" db:"string_fee"`
}

type InstrumentUpdates struct {
Type *string `json:"type" db:"type"`
Status *string `json:"status" db:"status"`
Tags *StringMap `json:"tags" db:"tags"`
Network *string `json:"network" db:"network"`
PublicKey *string `json:"publicKey" db:"public_key"`
Last4 *string `json:"last4" db:"last_4"`
UserID *string `json:"userId" db:"user_id"`
LocationID *sql.NullString `json:"locationId" db:"location_id"`
}

type TxLegUpdates struct {
Timestamp *time.Time `json:"timestamp" db:"timestamp"`
Amount *string `json:"amount" db:"amount"`
Expand Down
13 changes: 9 additions & 4 deletions pkg/repository/instrument.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import (
type Instrument interface {
Transactable
Create(model.Instrument) (model.Instrument, error)
GetById(id string) (model.Instrument, error)
GetWallet(addr string) (model.Instrument, error)
Update(ID string, updates any) error
GetById(id string) (model.Instrument, error)
GetWalletByAddr(addr string) (model.Instrument, error)
GetCardByFingerprint(fingerprint string) (m model.Instrument, err error)
GetWalletByUserId(userId string) (model.Instrument, error)
GetBankByUserId(userId string) (model.Instrument, error)
WalletAlreadyExists(addr string) (bool, error)
Expand Down Expand Up @@ -48,7 +49,7 @@ func (i instrument[T]) Create(insert model.Instrument) (model.Instrument, error)
return m, nil
}

func (i instrument[T]) GetWallet(addr string) (model.Instrument, error) {
func (i instrument[T]) GetWalletByAddr(addr string) (model.Instrument, error) {
m := model.Instrument{}
err := i.store.Get(&m, fmt.Sprintf("SELECT * FROM %s WHERE public_key = $1", i.table), addr)
if err != nil && err == sql.ErrNoRows {
Expand All @@ -59,6 +60,10 @@ func (i instrument[T]) GetWallet(addr string) (model.Instrument, error) {
return m, nil
}

func (i instrument[T]) GetCardByFingerprint(fingerprint string) (m model.Instrument, err error) {
return i.GetWalletByAddr(fingerprint)
}

func (i instrument[T]) GetWalletByUserId(userId string) (model.Instrument, error) {
m := model.Instrument{}
err := i.store.Get(&m, fmt.Sprintf("SELECT * FROM %s WHERE user_id = $1 AND type = 'Crypto Wallet'", i.table), userId)
Expand All @@ -82,7 +87,7 @@ func (i instrument[T]) GetBankByUserId(userId string) (model.Instrument, error)
}

func (i instrument[T]) WalletAlreadyExists(addr string) (bool, error) {
wallet, err := i.GetWallet(addr)
wallet, err := i.GetWalletByAddr(addr)

if err != nil && errors.Cause(err).Error() != "not found" { // because we are wrapping error and care about its value
return true, common.StringError(err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/service/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (a auth) VerifySignedPayload(request model.WalletSignaturePayloadSigned) (U
}

// Verify user is registered to this wallet address
instrument, err := a.repos.Instrument.GetWallet(payload.Address)
instrument, err := a.repos.Instrument.GetWalletByAddr(payload.Address)
if err != nil {
return resp, common.StringError(err)
}
Expand Down Expand Up @@ -204,7 +204,7 @@ func (a auth) RefreshToken(refreshToken string, walletAddress string) (UserCreat

// verify wallet address
// Verify user is registered to this wallet address
instrument, err := a.repos.Instrument.GetWallet(walletAddress)
instrument, err := a.repos.Instrument.GetWalletByAddr(walletAddress)
if err != nil {
if strings.Contains(err.Error(), "not found") {
return resp, common.StringError(errors.New("wallet address not associated with this user: " + walletAddress))
Expand Down
25 changes: 13 additions & 12 deletions pkg/service/checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ type AuthorizedCharge struct {
CardType string
}

func AuthorizeCharge(amount float64, userWallet string, tokenId string) (auth AuthorizedCharge, err error) {
func AuthorizeCharge(p transactionProcessingData) (transactionProcessingData, error) {
auth := AuthorizedCharge{}
config, err := getConfig()
if err != nil {
return auth, common.StringError(err)
return p, common.StringError(err)
}
client := payments.NewClient(*config)

Expand All @@ -75,25 +76,25 @@ func AuthorizeCharge(amount float64, userWallet string, tokenId string) (auth Au
Number: "4242424242424242", // Success
// Number: "4273149019799094", // succeed authorize, fail capture
// Number: "4544249167673670", // Declined - Insufficient funds
// Number: "5148447461737269", // Invalid transaction
// Number: "5148447461737269", // Invalid transaction (debit card)
ExpiryMonth: 2,
ExpiryYear: 2024,
Name: "Customer Name",
CVV: "100",
}
paymentToken, err := CreateToken(&card)
if err != nil {
return auth, common.StringError(err)
return p, common.StringError(err)
}
paymentTokenID = paymentToken.Created.Token
if tokenId != "" {
paymentTokenID = tokenId
if p.executionRequest.CardToken != "" {
paymentTokenID = p.executionRequest.CardToken
}
} else {
paymentTokenID = tokenId
paymentTokenID = p.executionRequest.CardToken
}

usd := convertAmount(amount)
usd := convertAmount(p.executionRequest.TotalUSD)

capture := false
request := &payments.Request{
Expand All @@ -104,7 +105,7 @@ func AuthorizeCharge(amount float64, userWallet string, tokenId string) (auth Au
Amount: usd,
Currency: "USD",
Customer: &payments.Customer{
Name: userWallet,
Name: p.executionRequest.UserAddress,
},
Capture: &capture,
}
Expand All @@ -115,7 +116,7 @@ func AuthorizeCharge(amount float64, userWallet string, tokenId string) (auth Au
}
response, err := client.Request(request, &params)
if err != nil {
return auth, common.StringError(err)
return p, common.StringError(err)
}

// Collect authorization ID and Instrument ID
Expand All @@ -132,9 +133,9 @@ func AuthorizeCharge(amount float64, userWallet string, tokenId string) (auth Au
auth.CheckoutFingerprint = response.Processed.Source.CardSourceResponse.Fingerprint
}
}

p.cardAuthorization = &auth
// TODO: Create entry for authorization in our DB associated with userWallet
return auth, nil
return p, nil
}

func CaptureCharge(amount float64, userWallet string, authorizationID string) (capture *payments.CapturesResponse, err error) {
Expand Down
32 changes: 17 additions & 15 deletions pkg/service/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,21 +449,27 @@ func verifyQuote(e model.ExecutionRequest, newEstimate model.Quote) (bool, error
return true, nil
}

func (t transaction) addCardInstrumentIdIfNew(fingerprint string, userID string, last4 string, cardType string) (string, error) {
instrument, err := t.repos.Instrument.GetWallet(fingerprint) // temporarily using get wallet and storing it there
func (t transaction) addCardInstrumentIdIfNew(p transactionProcessingData) (string, error) {
instrument, err := t.repos.Instrument.GetCardByFingerprint(p.cardAuthorization.CheckoutFingerprint)
if err != nil && !strings.Contains(err.Error(), "not found") { // because we are wrapping error and care about its value
return "", common.StringError(err)
} else if err == nil && instrument.UserID != "" {
return instrument.ID, nil // instrument already exists
}

// We should gather type from the payment processor
instrument_type := "DebitCard"
if cardType == "CREDIT" {
instrument_type = "CreditCard"
instrument_type := "Debit Card"
if p.cardAuthorization.CardType == "CREDIT" {
instrument_type = "Credit Card"
}
// Create a new instrument
instrument = model.Instrument{Type: instrument_type, Status: "authorized", Last4: last4, UserID: userID, PublicKey: fingerprint} // No locationID until fingerprint
instrument = model.Instrument{ // No locationID until fingerprint
Type: instrument_type,
Status: "created",
Last4: p.cardAuthorization.Last4,
UserID: *p.userId,
PublicKey: p.cardAuthorization.CheckoutFingerprint,
}
instrument, err = t.repos.Instrument.Create(instrument)
if err != nil {
return "", common.StringError(err)
Expand All @@ -473,7 +479,7 @@ func (t transaction) addCardInstrumentIdIfNew(fingerprint string, userID string,
}

func (t transaction) addWalletInstrumentIdIfNew(address string, id string) (string, error) {
instrument, err := t.repos.Instrument.GetWallet(address)
instrument, err := t.repos.Instrument.GetWalletByAddr(address)
if err != nil && !strings.Contains(err.Error(), "not found") {
return "", common.StringError(err)
} else if err == nil && instrument.PublicKey == address {
Expand All @@ -492,13 +498,13 @@ func (t transaction) addWalletInstrumentIdIfNew(address string, id string) (stri

func (t transaction) authCard(p transactionProcessingData) (transactionProcessingData, error) {
// auth their card
auth, err := AuthorizeCharge(p.executionRequest.TotalUSD, p.executionRequest.UserAddress, p.executionRequest.CardToken)
p, err := AuthorizeCharge(p)
if err != nil {
return p, common.StringError(err)
}

// Add Checkout Instrument ID to our DB if it's not there already and associate it with the user
instrumentId, err := t.addCardInstrumentIdIfNew(auth.CheckoutFingerprint, *p.userId, auth.Last4, auth.CardType)
instrumentId, err := t.addCardInstrumentIdIfNew(p)
if err != nil {
return p, common.StringError(err)
}
Expand All @@ -523,11 +529,7 @@ func (t transaction) authCard(p transactionProcessingData) (transactionProcessin
return p, common.StringError(err)
}

p.cardAuthorization = &auth
if err != nil {
return p, common.StringError(err)
}
err = t.updateTransactionStatus("Card "+auth.Status, p.transactionModel.ID)
err = t.updateTransactionStatus("Card "+p.cardAuthorization.Status, p.transactionModel.ID)
if err != nil {
return p, common.StringError(err)
}
Expand Down Expand Up @@ -560,7 +562,7 @@ func (t transaction) authCard(p transactionProcessingData) (transactionProcessin
return p, common.StringError(err)
}

if !auth.Approved {
if !p.cardAuthorization.Approved {
err := t.unit21CreateTransaction(p.transactionModel.ID)
if err != nil {
return p, common.StringError(err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/service/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func (u user) createUserData(addr string) (model.User, error) {
return user, common.StringError(err)
}
// Create a new wallet instrument and associate it with the new user
instrument := model.Instrument{Type: "crypto-wallet", Status: "verified", Network: "EVM", PublicKey: addr, UserID: user.ID}
instrument := model.Instrument{Type: "Crypto Wallet", Status: "verified", Network: "EVM", PublicKey: addr, UserID: user.ID}
instrument, err = u.repos.Instrument.Create(instrument)
if err != nil {
u.repos.Instrument.Rollback()
Expand Down