Skip to content

Commit 6dbaee9

Browse files
committed
Support mult-mint and multi-vm external deposits
1 parent 31761a4 commit 6dbaee9

File tree

6 files changed

+55
-46
lines changed

6 files changed

+55
-46
lines changed

pkg/code/async/geyser/backup.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
"github.com/newrelic/go-agent/v3/newrelic"
9+
"github.com/sirupsen/logrus"
910

1011
"github.com/code-payments/code-server/pkg/code/common"
1112
"github.com/code-payments/code-server/pkg/code/data/account"
@@ -146,9 +147,18 @@ func (p *service) backupExternalDepositWorker(serviceCtx context.Context, interv
146147
return
147148
}
148149

149-
log := log.WithField("authority", authorityAccount.PublicKey().ToBase58())
150+
mintAccount, err := common.NewAccountFromPublicKeyString(accountInfoRecord.MintAccount)
151+
if err != nil {
152+
log.WithError(err).Warn("invalid mint account")
153+
return
154+
}
155+
156+
log := log.WithFields(logrus.Fields{
157+
"authority": authorityAccount.PublicKey().ToBase58(),
158+
"mint": mintAccount.PublicKey().ToBase58(),
159+
})
150160

151-
err = fixMissingExternalDeposits(tracedCtx, p.data, p.vmIndexerClient, p.integration, authorityAccount)
161+
err = fixMissingExternalDeposits(tracedCtx, p.data, p.vmIndexerClient, p.integration, authorityAccount, mintAccount)
152162
if err != nil {
153163
log.WithError(err).Warn("failed to fix missing external deposits")
154164
}

pkg/code/async/geyser/external_deposit.go

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,20 @@ var (
3939
syncedDepositCache = cache.NewCache(1_000_000)
4040
)
4141

42-
func fixMissingExternalDeposits(ctx context.Context, data code_data.Provider, vmIndexerClient indexerpb.IndexerClient, integration Integration, userAuthority *common.Account) error {
43-
err := maybeInitiateExternalDepositIntoVm(ctx, data, vmIndexerClient, userAuthority)
42+
func fixMissingExternalDeposits(ctx context.Context, data code_data.Provider, vmIndexerClient indexerpb.IndexerClient, integration Integration, userAuthority, mint *common.Account) error {
43+
err := maybeInitiateExternalDepositIntoVm(ctx, data, vmIndexerClient, userAuthority, mint)
4444
if err != nil {
4545
return errors.Wrap(err, "error depositing into the vm")
4646
}
4747

48-
signatures, err := findPotentialExternalDepositsIntoVm(ctx, data, userAuthority)
48+
signatures, err := findPotentialExternalDepositsIntoVm(ctx, data, userAuthority, mint)
4949
if err != nil {
5050
return errors.Wrap(err, "error finding potential external deposits into vm")
5151
}
5252

5353
var anyError error
5454
for _, signature := range signatures {
55-
err := processPotentialExternalDepositIntoVm(ctx, data, integration, signature, userAuthority)
55+
err := processPotentialExternalDepositIntoVm(ctx, data, integration, signature, userAuthority, mint)
5656
if err != nil {
5757
anyError = errors.Wrap(err, "error processing signature for external deposit into vm")
5858
}
@@ -61,11 +61,11 @@ func fixMissingExternalDeposits(ctx context.Context, data code_data.Provider, vm
6161
return anyError
6262
}
6363

64-
return markDepositsAsSynced(ctx, data, userAuthority)
64+
return markDepositsAsSynced(ctx, data, userAuthority, mint)
6565
}
6666

67-
func maybeInitiateExternalDepositIntoVm(ctx context.Context, data code_data.Provider, vmIndexerClient indexerpb.IndexerClient, userAuthority *common.Account) error {
68-
vmConfig, err := common.GetVmConfigForMint(ctx, data, common.CoreMintAccount)
67+
func maybeInitiateExternalDepositIntoVm(ctx context.Context, data code_data.Provider, vmIndexerClient indexerpb.IndexerClient, userAuthority, mint *common.Account) error {
68+
vmConfig, err := common.GetVmConfigForMint(ctx, data, mint)
6969
if err != nil {
7070
return err
7171
}
@@ -85,11 +85,11 @@ func maybeInitiateExternalDepositIntoVm(ctx context.Context, data code_data.Prov
8585
if balance == 0 {
8686
return nil
8787
}
88-
return initiateExternalDepositIntoVm(ctx, data, vmIndexerClient, userAuthority, balance)
88+
return initiateExternalDepositIntoVm(ctx, data, vmIndexerClient, userAuthority, mint, balance)
8989
}
9090

91-
func initiateExternalDepositIntoVm(ctx context.Context, data code_data.Provider, vmIndexerClient indexerpb.IndexerClient, userAuthority *common.Account, balance uint64) error {
92-
vmConfig, err := common.GetVmConfigForMint(ctx, data, common.CoreMintAccount)
91+
func initiateExternalDepositIntoVm(ctx context.Context, data code_data.Provider, vmIndexerClient indexerpb.IndexerClient, userAuthority, mint *common.Account, balance uint64) error {
92+
vmConfig, err := common.GetVmConfigForMint(ctx, data, mint)
9393
if err != nil {
9494
return err
9595
}
@@ -99,25 +99,25 @@ func initiateExternalDepositIntoVm(ctx context.Context, data code_data.Provider,
9999
return errors.Wrap(err, "error getting vm deposit ata")
100100
}
101101

102-
memoryAccount, memoryIndex, err := getVirtualTimelockAccountLocationInMemory(ctx, vmIndexerClient, common.CodeVmAccount, userAuthority)
102+
memoryAccount, memoryIndex, err := getVirtualTimelockAccountLocationInMemory(ctx, vmIndexerClient, vmConfig.Vm, userAuthority)
103103
if err != nil {
104104
return errors.Wrap(err, "error getting vta location in memory")
105105
}
106106

107107
txn := solana.NewTransaction(
108-
common.GetSubsidizer().PublicKey().ToBytes(),
108+
vmConfig.Authority.PublicKey().ToBytes(),
109109
memo.Instruction(codeVmDepositMemoValue),
110110
compute_budget.SetComputeUnitPrice(1_000),
111111
compute_budget.SetComputeUnitLimit(50_000),
112112
cvm.NewDepositInstruction(
113113
&cvm.DepositInstructionAccounts{
114-
VmAuthority: common.GetSubsidizer().PublicKey().ToBytes(),
115-
Vm: common.CodeVmAccount.PublicKey().ToBytes(),
114+
VmAuthority: vmConfig.Authority.PublicKey().ToBytes(),
115+
Vm: vmConfig.Vm.PublicKey().ToBytes(),
116116
VmMemory: memoryAccount.PublicKey().ToBytes(),
117117
Depositor: vmDepositAccounts.VaultOwner.PublicKey().ToBytes(),
118118
DepositPda: vmDepositAccounts.Pda.PublicKey().ToBytes(),
119119
DepositAta: vmDepositAccounts.Ata.PublicKey().ToBytes(),
120-
VmOmnibus: common.CodeVmOmnibusAccount.PublicKey().ToBytes(),
120+
VmOmnibus: vmConfig.Omnibus.PublicKey().ToBytes(),
121121
},
122122
&cvm.DepositInstructionArgs{
123123
AccountIndex: memoryIndex,
@@ -133,7 +133,7 @@ func initiateExternalDepositIntoVm(ctx context.Context, data code_data.Provider,
133133
}
134134
txn.SetBlockhash(bh)
135135

136-
err = txn.Sign(common.GetSubsidizer().PrivateKey().ToBytes())
136+
err = txn.Sign(vmConfig.Authority.PrivateKey().ToBytes())
137137
if err != nil {
138138
return errors.Wrap(err, "error signing transaction")
139139
}
@@ -159,8 +159,8 @@ func initiateExternalDepositIntoVm(ctx context.Context, data code_data.Provider,
159159
return nil
160160
}
161161

162-
func findPotentialExternalDepositsIntoVm(ctx context.Context, data code_data.Provider, userAuthority *common.Account) ([]string, error) {
163-
vmConfig, err := common.GetVmConfigForMint(ctx, data, common.CoreMintAccount)
162+
func findPotentialExternalDepositsIntoVm(ctx context.Context, data code_data.Provider, userAuthority, mint *common.Account) ([]string, error) {
163+
vmConfig, err := common.GetVmConfigForMint(ctx, data, mint)
164164
if err != nil {
165165
return nil, err
166166
}
@@ -218,8 +218,8 @@ func findPotentialExternalDepositsIntoVm(ctx context.Context, data code_data.Pro
218218
}
219219
}
220220

221-
func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.Provider, integration Integration, signature string, userAuthority *common.Account) error {
222-
vmConfig, err := common.GetVmConfigForMint(ctx, data, common.CoreMintAccount)
221+
func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.Provider, integration Integration, signature string, userAuthority, mint *common.Account) error {
222+
vmConfig, err := common.GetVmConfigForMint(ctx, data, mint)
223223
if err != nil {
224224
return err
225225
}
@@ -253,13 +253,13 @@ func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.P
253253
return errors.Wrap(err, "error getting transaction token balances")
254254
}
255255

256-
// Check whether the VM authority was involved in this transaction as a signer.
257-
// If not, then it couldn't have been deposited into the VM
258-
if tokenBalances.Accounts[0] != common.GetSubsidizer().PublicKey().ToBase58() {
256+
// Check whether the VM authority or subsidizer was involved in this transaction
257+
// as a payer. If not, then it couldn't have been deposited into the VM
258+
if tokenBalances.Accounts[0] != vmConfig.Authority.PublicKey().ToBase58() && tokenBalances.Accounts[0] != common.GetSubsidizer().PublicKey().ToBase58() {
259259
return nil
260260
}
261261

262-
deltaQuarksIntoOmnibus, err := getDeltaQuarksFromTokenBalances(common.CodeVmOmnibusAccount, tokenBalances)
262+
deltaQuarksIntoOmnibus, err := getDeltaQuarksFromTokenBalances(vmConfig.Omnibus, tokenBalances)
263263
if err != nil {
264264
return errors.Wrap(err, "error getting delta quarks for vm omnibus from token balances")
265265
}
@@ -278,21 +278,21 @@ func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.P
278278
return nil
279279
}
280280

281-
accountInfoRecords, err := data.GetAccountInfoByAuthorityAddress(ctx, userAuthority.PublicKey().ToBase58())
281+
accountInfoRecordsByMint, err := data.GetAccountInfoByAuthorityAddress(ctx, userAuthority.PublicKey().ToBase58())
282282
if err != nil {
283283
return errors.Wrap(err, "error getting account info record")
284284
}
285-
coreMintAccountInfoRecord, ok := accountInfoRecords[common.CoreMintAccount.PublicKey().ToBase58()]
285+
accountInfoRecord, ok := accountInfoRecordsByMint[mint.PublicKey().ToBase58()]
286286
if !ok {
287287
return errors.New("core mint account info record doesn't exist")
288288
}
289-
userVirtualTimelockVaultAccount, err := common.NewAccountFromPublicKeyString(coreMintAccountInfoRecord.TokenAccount)
289+
userVirtualTimelockVaultAccount, err := common.NewAccountFromPublicKeyString(accountInfoRecord.TokenAccount)
290290
if err != nil {
291291
return errors.Wrap(err, "invalid virtual timelock vault account")
292292
}
293293

294294
// Use the account type to determine how we'll process this external deposit
295-
switch coreMintAccountInfoRecord.AccountType {
295+
switch accountInfoRecord.AccountType {
296296
case commonpb.AccountType_PRIMARY:
297297
// Check whether we've previously processed this external deposit
298298
_, err = data.GetExternalDeposit(ctx, signature, userVirtualTimelockVaultAccount.PublicKey().ToBase58())
@@ -303,12 +303,12 @@ func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.P
303303
return errors.Wrap(err, "error checking for existing external deposit record")
304304
}
305305

306-
ownerAccount, err := common.NewAccountFromPublicKeyString(coreMintAccountInfoRecord.OwnerAccount)
306+
ownerAccount, err := common.NewAccountFromPublicKeyString(accountInfoRecord.OwnerAccount)
307307
if err != nil {
308308
return errors.Wrap(err, "invalid owner account")
309309
}
310310

311-
usdMarketValue, _, err := currency_util.CalculateUsdMarketValue(ctx, data, common.CoreMintAccount, uint64(deltaQuarksIntoOmnibus), time.Now())
311+
usdMarketValue, _, err := currency_util.CalculateUsdMarketValue(ctx, data, mint, uint64(deltaQuarksIntoOmnibus), time.Now())
312312
if err != nil {
313313
return errors.Wrap(err, "error calculating usd market value")
314314
}
@@ -319,7 +319,7 @@ func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.P
319319
IntentId: getExternalDepositIntentID(signature, userVirtualTimelockVaultAccount),
320320
IntentType: intent.ExternalDeposit,
321321

322-
MintAccount: common.CoreMintAccount.PublicKey().ToBase58(),
322+
MintAccount: mint.PublicKey().ToBase58(),
323323

324324
InitiatorOwnerAccount: ownerAccount.PublicKey().ToBase58(),
325325

@@ -363,7 +363,7 @@ func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.P
363363
syncedDepositCache.Insert(cacheKey, true, 1)
364364

365365
// Best-effort processing for notification back to the user
366-
integration.OnDepositReceived(ctx, ownerAccount, uint64(deltaQuarksIntoOmnibus))
366+
integration.OnDepositReceived(ctx, ownerAccount, mint, uint64(deltaQuarksIntoOmnibus), usdMarketValue)
367367

368368
return nil
369369
default:
@@ -422,20 +422,20 @@ func getDeltaQuarksFromTokenBalances(tokenAccount *common.Account, tokenBalances
422422
return postQuarkBalance - preQuarkBalance, nil
423423
}
424424

425-
func markDepositsAsSynced(ctx context.Context, data code_data.Provider, userAuthority *common.Account) error {
425+
func markDepositsAsSynced(ctx context.Context, data code_data.Provider, userAuthority, mint *common.Account) error {
426426
accountInfoRecords, err := data.GetAccountInfoByAuthorityAddress(ctx, userAuthority.PublicKey().ToBase58())
427427
if err != nil {
428428
return errors.Wrap(err, "error getting account info record")
429429
}
430-
coreMintAccountInfoRecord, ok := accountInfoRecords[common.CoreMintAccount.PublicKey().ToBase58()]
430+
accountInfoRecord, ok := accountInfoRecords[mint.PublicKey().ToBase58()]
431431
if !ok {
432432
return errors.New("core mint account info record doesn't exist")
433433
}
434434

435-
coreMintAccountInfoRecord.RequiresDepositSync = false
436-
coreMintAccountInfoRecord.DepositsLastSyncedAt = time.Now()
435+
accountInfoRecord.RequiresDepositSync = false
436+
accountInfoRecord.DepositsLastSyncedAt = time.Now()
437437

438-
err = data.UpdateAccountInfo(ctx, coreMintAccountInfoRecord)
438+
err = data.UpdateAccountInfo(ctx, accountInfoRecord)
439439
if err != nil {
440440
return errors.Wrap(err, "error updating account info record")
441441
}

pkg/code/async/geyser/handler.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (h *TokenProgramAccountHandler) Handle(ctx context.Context, update *geyserp
8585

8686
switch mintAccount.PublicKey().ToBase58() {
8787

88-
case common.CoreMintAccount.PublicKey().ToBase58():
88+
case common.CoreMintAccount.PublicKey().ToBase58(), "52MNGpgvydSwCtC2H4qeiZXZ1TxEuRVCRGa8LAfk2kSj":
8989
// Not an ATA, so filter it out. It cannot be a VM deposit ATA
9090
if bytes.Equal(tokenAccount.PublicKey().ToBytes(), ownerAccount.PublicKey().ToBytes()) {
9191
return nil
@@ -98,21 +98,20 @@ func (h *TokenProgramAccountHandler) Handle(ctx context.Context, update *geyserp
9898
return nil
9999
}
100100

101-
err = processPotentialExternalDepositIntoVm(ctx, h.data, h.integration, signature, userAuthorityAccount)
101+
err = processPotentialExternalDepositIntoVm(ctx, h.data, h.integration, signature, userAuthorityAccount, mintAccount)
102102
if err != nil {
103103
return errors.Wrap(err, "error processing signature for external deposit into vm")
104104
}
105105

106106
if unmarshalled.Amount > 0 {
107-
err = initiateExternalDepositIntoVm(ctx, h.data, h.vmIndexerClient, userAuthorityAccount, unmarshalled.Amount)
107+
err = initiateExternalDepositIntoVm(ctx, h.data, h.vmIndexerClient, userAuthorityAccount, mintAccount, unmarshalled.Amount)
108108
if err != nil {
109109
return errors.Wrap(err, "error depositing into the vm")
110110
}
111111
}
112112

113113
return nil
114114
default:
115-
// Not a Core Mint account, so filter it out
116115
return nil
117116
}
118117
}

pkg/code/async/geyser/integration.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ import (
88

99
// Integration allows for notifications based on events processed by Geyser
1010
type Integration interface {
11-
OnDepositReceived(ctx context.Context, owner *common.Account, quarksReceived uint64) error
11+
OnDepositReceived(ctx context.Context, owner, mint *common.Account, quarksReceived uint64, usdMarketValue float64) error
1212
}

pkg/code/server/account/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func (s *server) GetTokenAccountInfos(ctx context.Context, req *accountpb.GetTok
238238

239239
// Trigger a deposit sync with the blockchain for the primary account, if it exists
240240
for _, records := range filteredRecords {
241-
if records.General.AccountType == commonpb.AccountType_PRIMARY && !records.General.RequiresDepositSync && records.General.MintAccount == common.CoreMintAccount.PublicKey().ToBase58() {
241+
if records.General.AccountType == commonpb.AccountType_PRIMARY && !records.General.RequiresDepositSync {
242242
records.General.RequiresDepositSync = true
243243
err = s.data.UpdateAccountInfo(ctx, records.General)
244244
if err != nil {

pkg/code/server/account/server_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ func TestGetTokenAccountInfos_UserAccounts_HappyPath(t *testing.T) {
249249
primaryAccountInfoRecordsByMint, err := env.data.GetLatestAccountInfoByOwnerAddressAndType(env.ctx, ownerAccount.PublicKey().ToBase58(), commonpb.AccountType_PRIMARY)
250250
require.NoError(t, err)
251251
assert.True(t, primaryAccountInfoRecordsByMint[common.CoreMintAccount.PublicKey().ToBase58()].RequiresDepositSync)
252-
assert.False(t, primaryAccountInfoRecordsByMint[jeffyVmConfig.Mint.PublicKey().ToBase58()].RequiresDepositSync)
252+
assert.True(t, primaryAccountInfoRecordsByMint[jeffyVmConfig.Mint.PublicKey().ToBase58()].RequiresDepositSync)
253253
}
254254

255255
func TestGetTokenAccountInfos_RemoteSendGiftCard_HappyPath(t *testing.T) {

0 commit comments

Comments
 (0)