Skip to content

Commit 7546369

Browse files
committed
Support on-demand account creation in Swap RPC
1 parent 882b175 commit 7546369

File tree

3 files changed

+86
-14
lines changed

3 files changed

+86
-14
lines changed

pkg/code/server/transaction/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const (
1919
defaultSubmitIntentTimeout = 5 * time.Second
2020

2121
SwapTimeoutConfigEnvName = envConfigPrefix + "SWAP_TIMEOUT"
22-
defaultSwapTimeout = 60 * time.Second
22+
defaultSwapTimeout = 120 * time.Second
2323

2424
ClientReceiveTimeoutConfigEnvName = envConfigPrefix + "CLIENT_RECEIVE_TIMEOUT"
2525
defaultClientReceiveTimeout = time.Second

pkg/code/server/transaction/swap.go

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ import (
2222

2323
"github.com/code-payments/code-server/pkg/code/common"
2424
currency_util "github.com/code-payments/code-server/pkg/code/currency"
25+
code_data "github.com/code-payments/code-server/pkg/code/data"
2526
"github.com/code-payments/code-server/pkg/code/data/deposit"
27+
"github.com/code-payments/code-server/pkg/code/data/fulfillment"
2628
"github.com/code-payments/code-server/pkg/code/data/intent"
29+
"github.com/code-payments/code-server/pkg/code/data/timelock"
2730
"github.com/code-payments/code-server/pkg/code/data/transaction"
2831
transaction_util "github.com/code-payments/code-server/pkg/code/transaction"
2932
"github.com/code-payments/code-server/pkg/grpc/client"
@@ -143,6 +146,46 @@ func (s *transactionServer) Swap(streamer transactionpb.Transaction_SwapServer)
143146
return handleSwapError(streamer, err)
144147
}
145148

149+
ownerDestinationTimelockVault, err := owner.ToTimelockVault(destinationVmConfig)
150+
if err != nil {
151+
log.WithError(err).Warn("failure getting owner destination timelock accounts")
152+
return handleSwapError(streamer, err)
153+
}
154+
ownerDestinationTimelockRecord, err := s.data.GetTimelockByVault(ctx, ownerDestinationTimelockVault.PublicKey().ToBase58())
155+
if err == timelock.ErrTimelockNotFound {
156+
return handleSwapError(streamer, NewSwapValidationError("destination timelock vault account not opened"))
157+
} else if err != nil {
158+
log.WithError(err).Warn("failure getting destination timelock record")
159+
return handleSwapError(streamer, err)
160+
}
161+
162+
//
163+
// Section: On-demand account creation
164+
//
165+
166+
// todo: commonalities here and in geyser external deposit flow
167+
// todo: this will live somewhere else once we add the state management system
168+
if !ownerDestinationTimelockRecord.ExistsOnBlockchain() {
169+
err = ensureVirtualTimelockAccountIsInitialzed(ctx, s.data, ownerDestinationTimelockRecord)
170+
if err != nil {
171+
log.WithError(err).Warn("failure scheduling destination timelock account initialization")
172+
return handleSwapError(streamer, err)
173+
}
174+
175+
for range 60 {
176+
time.Sleep(time.Second)
177+
178+
_, _, err = common.GetVirtualTimelockAccountLocationInMemory(ctx, s.vmIndexerClient, destinationVmConfig.Vm, owner)
179+
if err == nil {
180+
break
181+
}
182+
}
183+
if err != nil {
184+
log.WithError(err).Warn("timed out waiting for destination timelock account initialization")
185+
return handleSwapError(streamer, err)
186+
}
187+
}
188+
146189
//
147190
// Section: Transaction construction
148191
//
@@ -330,20 +373,15 @@ func (s *transactionServer) Swap(streamer transactionpb.Transaction_SwapServer)
330373
// Section: Balance and transaction history
331374
//
332375

333-
// todo: This will live somewhere else once we add the state management system
376+
// todo: commonalities here and in geyser external deposit flow
377+
// todo: this will live somewhere else once we add the state management system
334378
var waitForBalanceUpdate sync.WaitGroup
335379
waitForBalanceUpdate.Add(1)
336380
go func() {
337381
defer waitForBalanceUpdate.Done()
338382

339383
ctx := context.Background()
340384

341-
ownerDestinationTimelockVault, err := owner.ToTimelockVault(destinationVmConfig)
342-
if err != nil {
343-
log.WithError(err).Warn("failure getting owner destination timelock accounts")
344-
return
345-
}
346-
347385
var tokenBalances *solana.TransactionTokenBalances
348386
for range 30 {
349387
time.Sleep(time.Second)
@@ -490,12 +528,38 @@ func (s *transactionServer) boundedSwapRecv(ctx context.Context, streamer transa
490528
}
491529
}
492530

493-
type SwapServerParameters struct {
494-
ComputeUnitLimit uint32
495-
ComputeUnitPrice uint64
496-
MemoValue string
497-
MemoryAccount *common.Account
498-
MemoryIndex uint16
531+
func ensureVirtualTimelockAccountIsInitialzed(ctx context.Context, data code_data.Provider, timelockRecord *timelock.Record) error {
532+
if !timelockRecord.ExistsOnBlockchain() {
533+
initializeFulfillmentRecord, err := data.GetFirstSchedulableFulfillmentByAddressAsSource(ctx, timelockRecord.VaultAddress)
534+
if err != nil {
535+
return err
536+
}
537+
538+
if initializeFulfillmentRecord.FulfillmentType != fulfillment.InitializeLockedTimelockAccount {
539+
return errors.New("expected an initialize locked timelock account fulfillment")
540+
}
541+
542+
return markFulfillmentAsActivelyScheduled(ctx, data, initializeFulfillmentRecord)
543+
}
544+
545+
return nil
546+
}
547+
548+
func markFulfillmentAsActivelyScheduled(ctx context.Context, data code_data.Provider, fulfillmentRecord *fulfillment.Record) error {
549+
if fulfillmentRecord.Id == 0 {
550+
return nil
551+
}
552+
553+
if !fulfillmentRecord.DisableActiveScheduling {
554+
return nil
555+
}
556+
557+
if fulfillmentRecord.State != fulfillment.StateUnknown {
558+
return nil
559+
}
560+
561+
fulfillmentRecord.DisableActiveScheduling = false
562+
return data.UpdateFulfillment(ctx, fulfillmentRecord)
499563
}
500564

501565
func getDeltaQuarksFromTokenBalances(tokenAccount *common.Account, tokenBalances *solana.TransactionTokenBalances) (int64, error) {

pkg/code/server/transaction/swap_handler.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ import (
1717

1818
// todo: Move transaction-related stuff to the transaction utility package
1919

20+
type SwapServerParameters struct {
21+
ComputeUnitLimit uint32
22+
ComputeUnitPrice uint64
23+
MemoValue string
24+
MemoryAccount *common.Account
25+
MemoryIndex uint16
26+
}
27+
2028
type SwapHandler interface {
2129
// GetServerParameter gets the server parameters to return to client for the swap
2230
GetServerParameters() *SwapServerParameters

0 commit comments

Comments
 (0)