Created
July 15, 2025 14:47
-
-
Save billsbooth/63361e21244d46d3dfa341de632ce837 to your computer and use it in GitHub Desktop.
Backend Sign In Request
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const IdentityTokenHeader = "Privy-Id-Token" | |
// PART 1 | |
// PUBLIC API | |
func siwp(c wrappers.WriteApiContext) { | |
// Get the privy jwt token from the request cookies | |
privyJwtToken := c.GetHeader(IdentityTokenHeader) | |
if privyJwtToken == "" { | |
apierror.ErrResponse(c, apierror.NewBadRequestErr("Missing privy-id-token")) | |
return | |
} | |
refCode := c.Query("ref_code") | |
if refCode == "" { | |
// Place holder ref code. | |
refCode = "tomcat" | |
} | |
privyClient, err := apictx.GetPrivyClient(c) | |
if err != nil { | |
apierror.ErrResponse(c, err) | |
return | |
} | |
validateJwtRes, err := privyClient.ValidateJwtToken(privyJwtToken) | |
if err != nil { | |
apierror.ErrResponse(c, apierror.NewBadRequestWrappedErr(err, "Invalid jwt token")) | |
return | |
} | |
if validateJwtRes.EmailLinkedAccount == nil || validateJwtRes.EmailLinkedAccount.Address == "" { | |
apierror.ErrResponse(c, apierror.NewBadRequestErr("Email info not found on account")) | |
return | |
} | |
store, err := apictx.GetStore(c) | |
if err != nil { | |
apierror.ErrResponse(c, err) | |
return | |
} | |
authSvc, err := apictx.GetAuthService(c) | |
if err != nil { | |
apierror.ErrResponse(c, err) | |
return | |
} | |
account, getErr := store.AccountsV2().GetByPrivyId(c, validateJwtRes.PrivyUserId) | |
var ok bool | |
if ferror.IsNotFound(getErr) { | |
account, ok = doSignupV3( | |
c, | |
store, | |
authSvc, | |
validateJwtRes.PrivyUserId, | |
validateJwtRes.EmailLinkedAccount.Address, | |
pggenadapter.BlockchainPlatformSolana, | |
refCode, | |
) | |
if !ok { | |
// Error is handled in doSignupV3 | |
return | |
} | |
} else if getErr != nil { | |
apierror.ErrResponse(c, getErr) | |
return | |
} | |
err = authmiddleware.SetSessionV2Key(c, account.Id) | |
if err != nil { | |
apierror.ErrResponse(c, err) | |
return | |
} | |
res := LoginResponse{AccountAddress: account.Address} | |
result := rest.Result[LoginResponse]{ // nolint:exhaustruct // All fields not needed here | |
Success: true, | |
Result: res, | |
} | |
c.JSON(http.StatusOK, result) | |
} | |
// PART 2 | |
// SIGN UP FLOW | |
func doSignupV3( | |
c wrappers.WriteApiContext, | |
store state.ReadStore, | |
authSvc auth.Service, | |
privyUserId string, | |
email string, | |
platform pggenadapter.BlockchainPlatform, | |
refCode string, | |
) (accounts_v2.AccountV2, bool) { | |
// nolint:exhaustruct | |
z := accounts_v2.AccountV2{} | |
accountService, err := apictx.GetAccountService(c) | |
if err != nil { | |
apierror.ErrResponse(c, err) | |
//nolint:exhaustruct | |
return z, false | |
} | |
referralCodeReadService, err := apictx.GetReferralCodeReadService(c) | |
if err != nil { | |
apierror.ErrResponse(c, err) | |
return z, false | |
} | |
referralCodeWriteService, err := apictx.GetReferralCodeWriteService(c) | |
if err != nil { | |
apierror.ErrResponse(c, err) | |
return z, false | |
} | |
ts := futils.Now() | |
// Validate the referral code | |
referralCode, getReferralCodeErr := referralCodeReadService.GetReferralCodeByCode(c, store, refCode) | |
if ferror.IsNotFound(getReferralCodeErr) { | |
apierror.ErrResponse(c, apierror.NewBadRequestErr("Invalid referral code.")) | |
return z, false | |
} else if getReferralCodeErr != nil { | |
apierror.ErrResponse(c, getReferralCodeErr) | |
return z, false | |
} | |
if !referralCode.Unlimited && referralCode.Claimed > 0 { | |
apierror.ErrResponse(c, apierror.NewBadRequestErr("Referral code is already used")) | |
return z, false | |
} | |
accountId, err := accountIdGenerator.Get()() | |
if err != nil { | |
apierror.ErrResponse(c, ferror.Wrap(err, "unable to create account id")) | |
return z, false | |
} | |
var wallet server_wallets.ServerWallet | |
switch platform { | |
case enums.BlockchainPlatformSolana: | |
var err error | |
wallet, err = authSvc.CreateSolanaWallet(accountId) | |
if err != nil { | |
apierror.ErrResponse(c, ferror.Wrap(err, "unable to create wallet")) | |
return z, false | |
} | |
default: | |
apierror.ErrResponse(c, apierror.NewBadRequestErr("Unsupported platform")) | |
return z, false | |
} | |
var account accounts_v2.AccountV2 | |
var createAccountErr error | |
writeErr := store.Write(c, statelog.InputTypeSiwpCreateAccoount, func(stx state.WriteStore) error { | |
account, createAccountErr = accountService.CreateAccountV2( | |
stx, | |
platform, | |
wallet.Address, | |
nil, | |
nil, | |
nullable.ToPtr(email), | |
nullable.ToPtr(privyUserId), | |
ts, | |
nullable.ToPtr(accountId), | |
) | |
if createAccountErr != nil { | |
return createAccountErr | |
} | |
_, err = stx.ServerWallets().Upsert(wallet) | |
if err != nil { | |
return ferror.Wrap(err, "unable to upsert server wallet") | |
} | |
claimErr := referralCodeWriteService.ClaimReferralCodeTx(stx, referralCode.Id, account.Id, ts) | |
if claimErr != nil { | |
return claimErr | |
} | |
_, createRefErr := referralCodeWriteService.CreateReferralCodesTx(stx, &account.Id, nil, nil, AccountCreationRefCodes, false, ts) | |
if createRefErr != nil { | |
return createRefErr | |
} | |
return nil | |
}) | |
if writeErr != nil { | |
apierror.ErrResponse(c, writeErr) | |
return z, false | |
} | |
return account, true | |
} | |
var accountIdGenerator = concurrency.NewField(func() (uuid.UUID, error) { | |
return uuid.NewRandom() | |
}) | |
// Part 3: | |
// Setting the cookie | |
// "github.com/gorilla/sessions" | |
func SetSessionV2Key(c wrappers.ReadApiContext, accountID uuid.UUID) error { | |
session := c.SessionsDefaultMany(SessionKeyV2) | |
session.Set(SessionKeyV2, accountID.String()) | |
if err := session.Save(); err != nil { | |
return ferror.Wrap(err, "unable to save session") | |
} | |
return nil | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment