11package async_geyser
22
33import (
4+ "bytes"
45 "context"
56
67 "github.com/mr-tron/base58"
78 "github.com/pkg/errors"
89
910 geyserpb "github.com/code-payments/code-server/pkg/code/async/geyser/api/gen"
11+ indexerpb "github.com/code-payments/code-vm-indexer/generated/indexer/v1"
1012
13+ "github.com/code-payments/code-server/pkg/code/common"
1114 code_data "github.com/code-payments/code-server/pkg/code/data"
1215 "github.com/code-payments/code-server/pkg/solana/token"
1316)
@@ -25,110 +28,95 @@ type ProgramAccountUpdateHandler interface {
2528}
2629
2730type TokenProgramAccountHandler struct {
28- conf * conf
29- data code_data.Provider
31+ conf * conf
32+ data code_data.Provider
33+ vmIndexerClient indexerpb.IndexerClient
3034}
3135
32- func NewTokenProgramAccountHandler (conf * conf , data code_data.Provider ) ProgramAccountUpdateHandler {
36+ func NewTokenProgramAccountHandler (conf * conf , data code_data.Provider , vmIndexerClient indexerpb. IndexerClient ) ProgramAccountUpdateHandler {
3337 return & TokenProgramAccountHandler {
34- conf : conf ,
35- data : data ,
38+ conf : conf ,
39+ data : data ,
40+ vmIndexerClient : vmIndexerClient ,
3641 }
3742}
3843
39- // todo: implement real-time external deposits for the VM
44+ // todo: This needs to handle swaps
4045func (h * TokenProgramAccountHandler ) Handle (ctx context.Context , update * geyserpb.AccountUpdate ) error {
41- return nil
46+ if ! bytes .Equal (update .Owner , token .ProgramKey ) {
47+ return ErrUnexpectedProgramOwner
48+ }
4249
43- /*
44- if !bytes.Equal(update.Owner, token.ProgramKey) {
45- return ErrUnexpectedProgramOwner
46- }
50+ // We need to know the amount being deposited, and that's impossible without
51+ // a transaction signature.
52+ if update .TxSignature == nil {
53+ return nil
54+ }
4755
48- // We need to know the amount being deposited, and that's impossible without
49- // a transaction signature.
50- if update.TxSignature == nil {
51- return nil
52- }
56+ // We need to know more about the account before accessing our data stores,
57+ // so skip anything that doesn't have data. I'm assuming this means the account
58+ // is closed anyways.
59+ if len (update .Data ) == 0 {
60+ return nil
61+ }
5362
54- // We need to know more about the account before accessing our data stores,
55- // so skip anything that doesn't have data. I'm assuming this means the account
56- // is closed anyways.
57- if len(update.Data) == 0 {
58- return nil
59- }
63+ var unmarshalled token.Account
64+ if ! unmarshalled .Unmarshal (update .Data ) {
65+ // Probably not a token account (eg. mint)
66+ return nil
67+ }
6068
61- var unmarshalled token.Account
62- if !unmarshalled.Unmarshal(update.Data) {
63- // Probably not a token account (eg. mint)
64- return nil
65- }
69+ tokenAccount , err := common .NewAccountFromPublicKeyBytes (update .Pubkey )
70+ if err != nil {
71+ return errors .Wrap (err , "invalid token account" )
72+ }
6673
67- tokenAccount , err := common.NewAccountFromPublicKeyBytes(update.Pubkey )
68- if err != nil {
69- return errors.Wrap(err, "invalid token account")
70- }
74+ ownerAccount , err := common .NewAccountFromPublicKeyBytes (unmarshalled . Owner )
75+ if err != nil {
76+ return errors .Wrap (err , "invalid owner account" )
77+ }
7178
72- ownerAccount , err := common.NewAccountFromPublicKeyBytes(unmarshalled.Owner )
73- if err != nil {
74- return errors.Wrap(err, "invalid owner account")
75- }
79+ mintAccount , err := common .NewAccountFromPublicKeyBytes (unmarshalled .Mint )
80+ if err != nil {
81+ return errors .Wrap (err , "invalid mint account" )
82+ }
7683
77- mintAccount, err := common.NewAccountFromPublicKeyBytes(unmarshalled.Mint)
78- if err != nil {
79- return errors.Wrap(err, "invalid mint account")
80- }
84+ switch mintAccount .PublicKey ().ToBase58 () {
8185
82- // Account is empty, and all we care about are external deposits at this point,
83- // so filter it out
84- if unmarshalled.Amount == 0 {
86+ case common . CoreMintAccount . PublicKey (). ToBase58 ():
87+ // Not an ATA, so filter it out. It cannot be a VM deposit ATA
88+ if bytes . Equal ( tokenAccount . PublicKey (). ToBytes (), ownerAccount . PublicKey (). ToBytes ()) {
8589 return nil
8690 }
8791
88- switch mintAccount.PublicKey().ToBase58() {
89-
90- case common.CoreMintAccount.PublicKey().ToBase58():
91- // Not a program vault account, so filter it out. It cannot be a Timelock
92- // account.
93- if !bytes.Equal(tokenAccount.PublicKey().ToBytes(), ownerAccount.PublicKey().ToBytes()) {
94- return nil
95- }
96-
97- // todo: Need to implement VM deposit flow
92+ exists , userAuthorityAccount , err := testForKnownUserAuthorityFromDepositPda (ctx , h .data , tokenAccount )
93+ if err != nil {
94+ return errors .Wrap (err , "error testing for user authority from deposit pda" )
95+ } else if ! exists {
9896 return nil
97+ }
9998
100- case common.UsdcMintAccount.PublicKey().ToBase58():
101- ata, err := ownerAccount.ToAssociatedTokenAccount(common.UsdcMintAccount)
102- if err != nil {
103- return errors.Wrap(err, "error deriving usdc ata")
104- }
105-
106- // Not an ATA, so filter it out
107- if !bytes.Equal(tokenAccount.PublicKey().ToBytes(), ata.PublicKey().ToBytes()) {
108- return nil
109- }
99+ err = processPotentialExternalDepositIntoVm (ctx , h .data , * update .TxSignature , userAuthorityAccount )
100+ if err != nil {
101+ return errors .Wrap (err , "error processing signature for external deposit into vm" )
102+ }
110103
111- isCodeSwapAccount, err := testForKnownCodeSwapAccount(ctx, h.data, tokenAccount)
104+ if unmarshalled .Amount > 0 {
105+ err = maybeInitiateExternalDepositIntoVm (ctx , h .data , h .vmIndexerClient , userAuthorityAccount )
112106 if err != nil {
113- return errors.Wrap(err, "error testing for known account")
114- } else if !isCodeSwapAccount {
115- // Not an account we track, so skip the update
116- return nil
107+ return errors .Wrap (err , "error depositing into the vm" )
117108 }
118-
119- default:
120- // Not a Core Mint or USDC account, so filter it out
121- return nil
122109 }
123110
124- // We've determined this token account is one that we care about. Process
125- // the update as an external deposit.
126- return processPotentialExternalDeposit(ctx, h.conf, h.data, *update.TxSignature, tokenAccount)
127- */
111+ return nil
112+ default :
113+ // Not a Core Mint account, so filter it out
114+ return nil
115+ }
128116}
129117
130- func initializeProgramAccountUpdateHandlers (conf * conf , data code_data.Provider ) map [string ]ProgramAccountUpdateHandler {
118+ func initializeProgramAccountUpdateHandlers (conf * conf , data code_data.Provider , vmIndexerClient indexerpb. IndexerClient ) map [string ]ProgramAccountUpdateHandler {
131119 return map [string ]ProgramAccountUpdateHandler {
132- base58 .Encode (token .ProgramKey ): NewTokenProgramAccountHandler (conf , data ),
120+ base58 .Encode (token .ProgramKey ): NewTokenProgramAccountHandler (conf , data , vmIndexerClient ),
133121 }
134122}
0 commit comments