Skip to content

Commit e133cf8

Browse files
committed
Add swap created -> cancelling state logic
1 parent 231ded3 commit e133cf8

File tree

5 files changed

+122
-79
lines changed

5 files changed

+122
-79
lines changed

pkg/code/async/geyser/external_deposit.go

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"crypto/sha256"
66
"database/sql"
77
"fmt"
8-
"strconv"
98
"strings"
109
"time"
1110

@@ -22,6 +21,7 @@ import (
2221
"github.com/code-payments/code-server/pkg/code/data/deposit"
2322
"github.com/code-payments/code-server/pkg/code/data/intent"
2423
"github.com/code-payments/code-server/pkg/code/data/transaction"
24+
transaction_util "github.com/code-payments/code-server/pkg/code/transaction"
2525
"github.com/code-payments/code-server/pkg/database/query"
2626
"github.com/code-payments/code-server/pkg/retry"
2727
"github.com/code-payments/code-server/pkg/solana"
@@ -264,11 +264,11 @@ func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.P
264264
return nil
265265
}
266266

267-
deltaQuarksIntoOmnibus, err := getDeltaQuarksFromTokenBalances(vmConfig.Omnibus, tokenBalances)
267+
deltaQuarksIntoOmnibus, err := transaction_util.GetDeltaQuarksFromTokenBalances(vmConfig.Omnibus, tokenBalances)
268268
if err != nil {
269269
return errors.Wrap(err, "error getting delta quarks for vm omnibus from token balances")
270270
}
271-
deltaQuarksOutOfVmDepositAta, err := getDeltaQuarksFromTokenBalances(vmDepositAta, tokenBalances)
271+
deltaQuarksOutOfVmDepositAta, err := transaction_util.GetDeltaQuarksFromTokenBalances(vmDepositAta, tokenBalances)
272272
if err != nil {
273273
return errors.Wrap(err, "error getting delta quarks for vm deposit ata from token balances")
274274
}
@@ -386,31 +386,6 @@ func processPotentialExternalDepositIntoVm(ctx context.Context, data code_data.P
386386
}
387387
}
388388

389-
func getDeltaQuarksFromTokenBalances(tokenAccount *common.Account, tokenBalances *solana.TransactionTokenBalances) (int64, error) {
390-
var preQuarkBalance, postQuarkBalance int64
391-
var err error
392-
for _, tokenBalance := range tokenBalances.PreTokenBalances {
393-
if tokenBalances.Accounts[tokenBalance.AccountIndex] == tokenAccount.PublicKey().ToBase58() {
394-
preQuarkBalance, err = strconv.ParseInt(tokenBalance.TokenAmount.Amount, 10, 64)
395-
if err != nil {
396-
return 0, errors.Wrap(err, "error parsing pre token balance")
397-
}
398-
break
399-
}
400-
}
401-
for _, tokenBalance := range tokenBalances.PostTokenBalances {
402-
if tokenBalances.Accounts[tokenBalance.AccountIndex] == tokenAccount.PublicKey().ToBase58() {
403-
postQuarkBalance, err = strconv.ParseInt(tokenBalance.TokenAmount.Amount, 10, 64)
404-
if err != nil {
405-
return 0, errors.Wrap(err, "error parsing post token balance")
406-
}
407-
break
408-
}
409-
}
410-
411-
return postQuarkBalance - preQuarkBalance, nil
412-
}
413-
414389
func markDepositsAsSynced(ctx context.Context, data code_data.Provider, userAuthority, mint *common.Account) error {
415390
accountInfoRecords, err := data.GetAccountInfoByAuthorityAddress(ctx, userAuthority.PublicKey().ToBase58())
416391
if err != nil {

pkg/code/async/swap/config.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package async_swap
22

33
import (
4+
"time"
5+
46
"github.com/code-payments/code-server/pkg/config"
57
"github.com/code-payments/code-server/pkg/config/env"
68
)
@@ -10,10 +12,14 @@ const (
1012

1113
BatchSizeConfigEnvName = envConfigPrefix + "WORKER_BATCH_SIZE"
1214
defaultFulfillmentBatchSize = 100
15+
16+
ClientFundingTimeoutConfigEnvName = envConfigPrefix + "CLIENT_FUNDING_TIMEOUT"
17+
defaultClientFundingTimeout = 3 * time.Minute
1318
)
1419

1520
type conf struct {
16-
batchSize config.Uint64
21+
batchSize config.Uint64
22+
clientFundingTimeout config.Duration
1723
}
1824

1925
// ConfigProvider defines how config values are pulled
@@ -23,7 +29,8 @@ type ConfigProvider func() *conf
2329
func WithEnvConfigs() ConfigProvider {
2430
return func() *conf {
2531
return &conf{
26-
batchSize: env.NewUint64Config(BatchSizeConfigEnvName, defaultFulfillmentBatchSize),
32+
batchSize: env.NewUint64Config(BatchSizeConfigEnvName, defaultFulfillmentBatchSize),
33+
clientFundingTimeout: env.NewDurationConfig(ClientFundingTimeoutConfigEnvName, defaultClientFundingTimeout),
2734
}
2835
}
2936
}

pkg/code/async/swap/util.go

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"crypto/sha256"
66
"database/sql"
77
"fmt"
8-
"strconv"
8+
"slices"
99
"time"
1010

1111
"github.com/mr-tron/base58"
@@ -18,14 +18,12 @@ import (
1818
"github.com/code-payments/code-server/pkg/code/data/nonce"
1919
"github.com/code-payments/code-server/pkg/code/data/swap"
2020
"github.com/code-payments/code-server/pkg/code/data/transaction"
21-
"github.com/code-payments/code-server/pkg/solana"
21+
transaction_util "github.com/code-payments/code-server/pkg/code/transaction"
2222
)
2323

2424
func (p *service) validateSwapState(record *swap.Record, states ...swap.State) error {
25-
for _, validState := range states {
26-
if record.State == validState {
27-
return nil
28-
}
25+
if slices.Contains(states, record.State) {
26+
return nil
2927
}
3028
return errors.New("invalid swap state")
3129
}
@@ -41,35 +39,56 @@ func (p *service) markSwapFunded(ctx context.Context, record *swap.Record) error
4139
}
4240

4341
func (p *service) markSwapFinalized(ctx context.Context, record *swap.Record) error {
44-
err := p.validateSwapState(record, swap.StateSubmitting)
45-
if err != nil {
46-
return err
47-
}
42+
return p.data.ExecuteInTx(ctx, sql.LevelDefault, func(ctx context.Context) error {
43+
err := p.validateSwapState(record, swap.StateSubmitting)
44+
if err != nil {
45+
return err
46+
}
4847

49-
err = p.markNonceReleasedDueToSubmittedTransaction(ctx, record)
50-
if err != nil {
51-
return err
52-
}
48+
err = p.markNonceReleasedDueToSubmittedTransaction(ctx, record)
49+
if err != nil {
50+
return err
51+
}
5352

54-
record.TransactionBlob = nil
55-
record.State = swap.StateFinalized
56-
return p.data.SaveSwap(ctx, record)
53+
record.TransactionBlob = nil
54+
record.State = swap.StateFinalized
55+
return p.data.SaveSwap(ctx, record)
56+
})
5757
}
5858

5959
func (p *service) markSwapFailed(ctx context.Context, record *swap.Record) error {
60-
err := p.validateSwapState(record, swap.StateSubmitting)
61-
if err != nil {
62-
return err
63-
}
60+
return p.data.ExecuteInTx(ctx, sql.LevelDefault, func(ctx context.Context) error {
61+
err := p.validateSwapState(record, swap.StateSubmitting)
62+
if err != nil {
63+
return err
64+
}
6465

65-
err = p.markNonceReleasedDueToSubmittedTransaction(ctx, record)
66-
if err != nil {
67-
return err
68-
}
66+
err = p.markNonceReleasedDueToSubmittedTransaction(ctx, record)
67+
if err != nil {
68+
return err
69+
}
6970

70-
record.TransactionBlob = nil
71-
record.State = swap.StateFailed
72-
return p.data.SaveSwap(ctx, record)
71+
record.TransactionBlob = nil
72+
record.State = swap.StateFailed
73+
return p.data.SaveSwap(ctx, record)
74+
})
75+
}
76+
77+
func (p *service) markSwapCancelled(ctx context.Context, record *swap.Record) error {
78+
return p.data.ExecuteInTx(ctx, sql.LevelDefault, func(ctx context.Context) error {
79+
err := p.validateSwapState(record, swap.StateCreated)
80+
if err != nil {
81+
return err
82+
}
83+
84+
err = p.markNonceAvailableDueToCancelledSwap(ctx, record)
85+
if err != nil {
86+
return err
87+
}
88+
89+
record.State = swap.StateCancelled
90+
return p.data.SaveSwap(ctx, record)
91+
})
7392
}
7493

7594
// todo: commonalities between this and geyser external deposit logic
@@ -99,7 +118,7 @@ func (p *service) updateBalances(ctx context.Context, record *swap.Record) error
99118
return err
100119
}
101120

102-
deltaQuarksIntoOmnibus, err := getDeltaQuarksFromTokenBalances(destinationVmConfig.Omnibus, tokenBalances)
121+
deltaQuarksIntoOmnibus, err := transaction_util.GetDeltaQuarksFromTokenBalances(destinationVmConfig.Omnibus, tokenBalances)
103122
if err != nil {
104123
return err
105124
}
@@ -207,29 +226,32 @@ func (p *service) markNonceReleasedDueToSubmittedTransaction(ctx context.Context
207226
return p.data.SaveNonce(ctx, nonceRecord)
208227
}
209228

210-
func getDeltaQuarksFromTokenBalances(tokenAccount *common.Account, tokenBalances *solana.TransactionTokenBalances) (int64, error) {
211-
var preQuarkBalance, postQuarkBalance int64
212-
var err error
213-
for _, tokenBalance := range tokenBalances.PreTokenBalances {
214-
if tokenBalances.Accounts[tokenBalance.AccountIndex] == tokenAccount.PublicKey().ToBase58() {
215-
preQuarkBalance, err = strconv.ParseInt(tokenBalance.TokenAmount.Amount, 10, 64)
216-
if err != nil {
217-
return 0, errors.Wrap(err, "error parsing pre token balance")
218-
}
219-
break
220-
}
229+
func (p *service) markNonceAvailableDueToCancelledSwap(ctx context.Context, record *swap.Record) error {
230+
err := p.validateSwapState(record, swap.StateCreated)
231+
if err != nil {
232+
return err
221233
}
222-
for _, tokenBalance := range tokenBalances.PostTokenBalances {
223-
if tokenBalances.Accounts[tokenBalance.AccountIndex] == tokenAccount.PublicKey().ToBase58() {
224-
postQuarkBalance, err = strconv.ParseInt(tokenBalance.TokenAmount.Amount, 10, 64)
225-
if err != nil {
226-
return 0, errors.Wrap(err, "error parsing post token balance")
227-
}
228-
break
229-
}
234+
235+
nonceRecord, err := p.data.GetNonce(ctx, record.Nonce)
236+
if err != nil {
237+
return err
238+
}
239+
240+
if record.ProofSignature != nonceRecord.Signature {
241+
return errors.New("unexpected nonce signature")
242+
}
243+
244+
if record.Blockhash != nonceRecord.Blockhash {
245+
return errors.New("unexpected nonce blockhash")
246+
}
247+
248+
if nonceRecord.State != nonce.StateReserved {
249+
return errors.New("unexpected nonce state")
230250
}
231251

232-
return postQuarkBalance - preQuarkBalance, nil
252+
nonceRecord.State = nonce.StateAvailable
253+
nonceRecord.Signature = ""
254+
return p.data.SaveNonce(ctx, nonceRecord)
233255
}
234256

235257
func getSwapDepositIntentID(signature string, destination *common.Account) string {

pkg/code/async/swap/worker.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ func (p *service) handleStateCreated(ctx context.Context, record *swap.Record) e
8888
return err
8989
}
9090

91+
if time.Since(record.CreatedAt) > p.conf.clientFundingTimeout.Get(ctx) {
92+
return p.markSwapCancelled(ctx, record)
93+
}
94+
9195
return nil
9296
}
9397

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package transaction
2+
3+
import (
4+
"strconv"
5+
6+
"github.com/pkg/errors"
7+
8+
"github.com/code-payments/code-server/pkg/code/common"
9+
"github.com/code-payments/code-server/pkg/solana"
10+
)
11+
12+
func GetDeltaQuarksFromTokenBalances(tokenAccount *common.Account, tokenBalances *solana.TransactionTokenBalances) (int64, error) {
13+
var preQuarkBalance, postQuarkBalance int64
14+
var err error
15+
for _, tokenBalance := range tokenBalances.PreTokenBalances {
16+
if tokenBalances.Accounts[tokenBalance.AccountIndex] == tokenAccount.PublicKey().ToBase58() {
17+
preQuarkBalance, err = strconv.ParseInt(tokenBalance.TokenAmount.Amount, 10, 64)
18+
if err != nil {
19+
return 0, errors.Wrap(err, "error parsing pre token balance")
20+
}
21+
break
22+
}
23+
}
24+
for _, tokenBalance := range tokenBalances.PostTokenBalances {
25+
if tokenBalances.Accounts[tokenBalance.AccountIndex] == tokenAccount.PublicKey().ToBase58() {
26+
postQuarkBalance, err = strconv.ParseInt(tokenBalance.TokenAmount.Amount, 10, 64)
27+
if err != nil {
28+
return 0, errors.Wrap(err, "error parsing post token balance")
29+
}
30+
break
31+
}
32+
}
33+
34+
return postQuarkBalance - preQuarkBalance, nil
35+
}

0 commit comments

Comments
 (0)