Skip to content

Commit f259661

Browse files
committed
Support unlock state detection for lazy loaded Timelock accounts on the blockchain
1 parent 38d8586 commit f259661

File tree

6 files changed

+19
-15
lines changed

6 files changed

+19
-15
lines changed

pkg/code/async/geyser/backup.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
// the case? Real time updates. Backup workers likely won't be able to guarantee
2222
// real time (or near real time) updates at scale.
2323

24-
func (p *service) backupTimelockStateWorker(serviceCtx context.Context, interval time.Duration) error {
24+
func (p *service) backupTimelockStateWorker(serviceCtx context.Context, state timelock_token.TimelockState, interval time.Duration) error {
2525
log := p.log.WithField("method", "backupTimelockStateWorker")
2626
log.Debug("worker started")
2727

@@ -52,7 +52,7 @@ func (p *service) backupTimelockStateWorker(serviceCtx context.Context, interval
5252

5353
timelockRecords, err := p.data.GetAllTimelocksByState(
5454
tracedCtx,
55-
timelock_token.StateLocked,
55+
state,
5656
query.WithDirection(query.Ascending),
5757
query.WithCursor(cursor),
5858
query.WithLimit(256),

pkg/code/async/geyser/service.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/sirupsen/logrus"
99

1010
geyserpb "github.com/code-payments/code-server/pkg/code/async/geyser/api/gen"
11+
timelock_token "github.com/code-payments/code-server/pkg/solana/timelock/v1"
1112
indexerpb "github.com/code-payments/code-vm-indexer/generated/indexer/v1"
1213

1314
"github.com/code-payments/code-server/pkg/code/async"
@@ -63,7 +64,13 @@ func New(data code_data.Provider, vmIndexerClient indexerpb.IndexerClient, integ
6364
func (p *service) Start(ctx context.Context, _ time.Duration) error {
6465
// Start backup workers to catch missed events
6566
go func() {
66-
err := p.backupTimelockStateWorker(ctx, p.conf.backupTimelockWorkerInterval.Get(ctx))
67+
err := p.backupTimelockStateWorker(ctx, timelock_token.StateLocked, p.conf.backupTimelockWorkerInterval.Get(ctx))
68+
if err != nil && err != context.Canceled {
69+
p.log.WithError(err).Warn("timelock backup worker terminated unexpectedly")
70+
}
71+
}()
72+
go func() {
73+
err := p.backupTimelockStateWorker(ctx, timelock_token.StateUnknown, p.conf.backupTimelockWorkerInterval.Get(ctx))
6774
if err != nil && err != context.Canceled {
6875
p.log.WithError(err).Warn("timelock backup worker terminated unexpectedly")
6976
}

pkg/code/async/geyser/timelock.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ import (
1313
)
1414

1515
func updateTimelockAccountRecord(ctx context.Context, data code_data.Provider, timelockRecord *timelock.Record) error {
16-
// Wait for Timelock account initialization before monitoring state
17-
// to avoid conflicting with the sequencer
18-
if timelockRecord.VaultState == timelock_token.StateUnknown || timelockRecord.Block == 0 {
19-
return nil
20-
}
21-
2216
unlockState, slot, err := getTimelockUnlockState(ctx, data, timelockRecord)
2317
if err != nil {
2418
return err

pkg/code/async/sequencer/fulfillment_handler.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,6 @@ func (h *InitializeLockedTimelockAccountFulfillmentHandler) CanSubmitToBlockchai
8585
return false, errors.New("invalid fulfillment type")
8686
}
8787

88-
// todo: Fix unlock state detection for Timelock accounts that won't be
89-
// initialized immediately
90-
return true, nil
91-
9288
accountInfoRecord, err := h.data.GetAccountInfoByTokenAddress(ctx, fulfillmentRecord.Source)
9389
if err != nil {
9490
return false, err
@@ -101,7 +97,9 @@ func (h *InitializeLockedTimelockAccountFulfillmentHandler) CanSubmitToBlockchai
10197

10298
// Every other account type needs to be used in a transfer of funds to be opened
10399
nextScheduledFulfillment, err := h.data.GetNextSchedulableFulfillmentByAddress(ctx, fulfillmentRecord.Source, fulfillmentRecord.IntentOrderingIndex, fulfillmentRecord.ActionId, fulfillmentRecord.FulfillmentOrderingIndex)
104-
if err != nil {
100+
if err == fulfillment.ErrFulfillmentNotFound {
101+
return false, nil
102+
} else if err != nil {
105103
return false, err
106104
}
107105

pkg/code/async/sequencer/timelock.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ func markTimelockLocked(ctx context.Context, data code_data.Provider, vault stri
1919
return err
2020
}
2121

22-
if record.VaultState == timelock_token_v1.StateLocked {
22+
switch record.VaultState {
23+
case timelock_token_v1.StateLocked, timelock_token_v1.StateWaitingForTimeout, timelock_token_v1.StateUnlocked:
24+
return nil
25+
}
26+
if record.Block <= slot {
2327
return nil
2428
}
2529

pkg/code/server/transaction/action_handler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ func (h *OpenAccountActionHandler) GetFulfillmentMetadata(
166166
source: h.timelockAccounts.Vault,
167167
destination: nil,
168168
fulfillmentOrderingIndex: 0,
169+
disableActiveScheduling: h.accountType != commonpb.AccountType_PRIMARY, // Non-primary accounts are created on demand after first usage
169170
}, nil
170171
default:
171172
return nil, errors.New("invalid virtual ixn index")

0 commit comments

Comments
 (0)