@@ -3,6 +3,7 @@ package async_account
3
3
import (
4
4
"context"
5
5
"crypto/sha256"
6
+ "database/sql"
6
7
"errors"
7
8
"math"
8
9
"sync"
@@ -97,7 +98,7 @@ func (p *service) maybeInitiateGiftCardAutoReturn(ctx context.Context, accountIn
97
98
log .Trace ("gift card is claimed and will be removed from worker queue" )
98
99
99
100
// Cleanup anything related to gift card auto-return, since it cannot be scheduled
100
- err = p . initiateProcessToCleanupGiftCardAutoReturn (ctx , giftCardVaultAccount )
101
+ err = initiateProcessToCleanupGiftCardAutoReturn (ctx , p . data , giftCardVaultAccount )
101
102
if err != nil {
102
103
log .WithError (err ).Warn ("failure cleaning up auto-return action" )
103
104
return err
@@ -123,7 +124,7 @@ func (p *service) maybeInitiateGiftCardAutoReturn(ctx context.Context, accountIn
123
124
// There's no action to claim the gift card and the expiry window has been met.
124
125
// It's time to initiate the process of auto-returning the funds back to the
125
126
// issuer.
126
- err = p . initiateProcessToAutoReturnGiftCard (ctx , giftCardVaultAccount )
127
+ err = InitiateProcessToAutoReturnGiftCard (ctx , p . data , giftCardVaultAccount , false )
127
128
if err != nil {
128
129
log .WithError (err ).Warn ("failure initiating process to return gift card balance to issuer" )
129
130
return err
@@ -133,84 +134,91 @@ func (p *service) maybeInitiateGiftCardAutoReturn(ctx context.Context, accountIn
133
134
134
135
// Note: This is the first instance of handling a conditional action, and could be
135
136
// a good guide for similar actions in the future.
136
- func (p * service ) initiateProcessToAutoReturnGiftCard (ctx context.Context , giftCardVaultAccount * common.Account ) error {
137
- giftCardIssuedIntent , err := p .data .GetOriginalGiftCardIssuedIntent (ctx , giftCardVaultAccount .PublicKey ().ToBase58 ())
138
- if err != nil {
139
- return err
140
- }
137
+ //
138
+ // todo: This probably belongs somewhere more common
139
+ func InitiateProcessToAutoReturnGiftCard (ctx context.Context , data code_data.Provider , giftCardVaultAccount * common.Account , isVoidedByUser bool ) error {
140
+ return data .ExecuteInTx (ctx , sql .LevelDefault , func (ctx context.Context ) error {
141
+ giftCardIssuedIntent , err := data .GetOriginalGiftCardIssuedIntent (ctx , giftCardVaultAccount .PublicKey ().ToBase58 ())
142
+ if err != nil {
143
+ return err
144
+ }
141
145
142
- autoReturnAction , err := p .data .GetGiftCardAutoReturnAction (ctx , giftCardVaultAccount .PublicKey ().ToBase58 ())
143
- if err != nil {
144
- return err
145
- }
146
+ autoReturnAction , err := data .GetGiftCardAutoReturnAction (ctx , giftCardVaultAccount .PublicKey ().ToBase58 ())
147
+ if err != nil {
148
+ return err
149
+ }
150
+ if autoReturnAction .State != action .StateUnknown {
151
+ return nil
152
+ }
146
153
147
- autoReturnFulfillment , err := p . data .GetAllFulfillmentsByAction (ctx , autoReturnAction .Intent , autoReturnAction .ActionId )
148
- if err != nil {
149
- return err
150
- }
154
+ autoReturnFulfillment , err := data .GetAllFulfillmentsByAction (ctx , autoReturnAction .Intent , autoReturnAction .ActionId )
155
+ if err != nil {
156
+ return err
157
+ }
151
158
152
- // Add a intent record to show the funds being returned back to the issuer
153
- err = insertAutoReturnIntentRecord (ctx , p . data , giftCardIssuedIntent )
154
- if err != nil {
155
- return err
156
- }
159
+ // Add a intent record to show the funds being returned back to the issuer
160
+ err = insertAutoReturnIntentRecord (ctx , data , giftCardIssuedIntent , isVoidedByUser )
161
+ if err != nil {
162
+ return err
163
+ }
157
164
158
- // We need to update pre-sorting because auto-return fulfillments are always
159
- // inserted at the very last spot in the line.
160
- //
161
- // Must be the first thing to succeed! By pre-sorting this to the end of
162
- // the gift card issued intent, we ensure the auto-return is blocked on any
163
- // fulfillments to setup the gift card. We'll also guarantee that subsequent
164
- // intents that utilize the primary account as a source of funds will be blocked
165
- // by the auto-return.
166
- err = updateAutoReturnFulfillmentPreSorting (
167
- ctx ,
168
- p . data ,
169
- autoReturnFulfillment [0 ],
170
- giftCardIssuedIntent .Id ,
171
- math .MaxInt32 ,
172
- 0 ,
173
- )
174
- if err != nil {
175
- return err
176
- }
165
+ // We need to update pre-sorting because auto-return fulfillments are always
166
+ // inserted at the very last spot in the line.
167
+ //
168
+ // Must be the first thing to succeed! By pre-sorting this to the end of
169
+ // the gift card issued intent, we ensure the auto-return is blocked on any
170
+ // fulfillments to setup the gift card. We'll also guarantee that subsequent
171
+ // intents that utilize the primary account as a source of funds will be blocked
172
+ // by the auto-return.
173
+ err = updateAutoReturnFulfillmentPreSorting (
174
+ ctx ,
175
+ data ,
176
+ autoReturnFulfillment [0 ],
177
+ giftCardIssuedIntent .Id ,
178
+ math .MaxInt32 ,
179
+ 0 ,
180
+ )
181
+ if err != nil {
182
+ return err
183
+ }
177
184
178
- // This will update the action's quantity, so balance changes are reflected. We
179
- // also unblock fulfillment scheduling by moving the action out of the unknown
180
- // state and into the pending state.
181
- err = scheduleAutoReturnAction (
182
- ctx ,
183
- p . data ,
184
- autoReturnAction ,
185
- giftCardIssuedIntent .SendPublicPaymentMetadata .Quantity ,
186
- )
187
- if err != nil {
188
- return err
189
- }
185
+ // This will update the action's quantity, so balance changes are reflected. We
186
+ // also unblock fulfillment scheduling by moving the action out of the unknown
187
+ // state and into the pending state.
188
+ err = scheduleAutoReturnAction (
189
+ ctx ,
190
+ data ,
191
+ autoReturnAction ,
192
+ giftCardIssuedIntent .SendPublicPaymentMetadata .Quantity ,
193
+ )
194
+ if err != nil {
195
+ return err
196
+ }
190
197
191
- // This will trigger the fulfillment worker to poll for the fulfillment. This
192
- // should be the very last DB update called.
193
- return markFulfillmentAsActivelyScheduled (ctx , p .data , autoReturnFulfillment [0 ])
198
+ // This will trigger the fulfillment worker to poll for the fulfillment. This
199
+ // should be the very last DB update called.
200
+ return markFulfillmentAsActivelyScheduled (ctx , data , autoReturnFulfillment [0 ])
201
+ })
194
202
}
195
203
196
- func ( p * service ) initiateProcessToCleanupGiftCardAutoReturn (ctx context.Context , giftCardVaultAccount * common.Account ) error {
197
- autoReturnAction , err := p . data .GetGiftCardAutoReturnAction (ctx , giftCardVaultAccount .PublicKey ().ToBase58 ())
204
+ func initiateProcessToCleanupGiftCardAutoReturn (ctx context.Context , data code_data. Provider , giftCardVaultAccount * common.Account ) error {
205
+ autoReturnAction , err := data .GetGiftCardAutoReturnAction (ctx , giftCardVaultAccount .PublicKey ().ToBase58 ())
198
206
if err != nil {
199
207
return err
200
208
}
201
209
202
- autoReturnFulfillment , err := p . data .GetAllFulfillmentsByAction (ctx , autoReturnAction .Intent , autoReturnAction .ActionId )
210
+ autoReturnFulfillment , err := data .GetAllFulfillmentsByAction (ctx , autoReturnAction .Intent , autoReturnAction .ActionId )
203
211
if err != nil {
204
212
return err
205
213
}
206
214
207
- err = markActionAsRevoked (ctx , p . data , autoReturnAction )
215
+ err = markActionAsRevoked (ctx , data , autoReturnAction )
208
216
if err != nil {
209
217
return err
210
218
}
211
219
212
220
// The sequencer will handle state transition and any cleanup
213
- return markFulfillmentAsActivelyScheduled (ctx , p . data , autoReturnFulfillment [0 ])
221
+ return markFulfillmentAsActivelyScheduled (ctx , data , autoReturnFulfillment [0 ])
214
222
}
215
223
216
224
func markAutoReturnCheckComplete (ctx context.Context , data code_data.Provider , record * account.Record ) error {
@@ -274,7 +282,7 @@ func updateAutoReturnFulfillmentPreSorting(
274
282
return data .UpdateFulfillment (ctx , fulfillmentRecord )
275
283
}
276
284
277
- func insertAutoReturnIntentRecord (ctx context.Context , data code_data.Provider , giftCardIssuedIntent * intent.Record ) error {
285
+ func insertAutoReturnIntentRecord (ctx context.Context , data code_data.Provider , giftCardIssuedIntent * intent.Record , isVoidedByUser bool ) error {
278
286
usdExchangeRecord , err := data .GetExchangeRate (ctx , currency .USD , time .Now ())
279
287
if err != nil {
280
288
return err
@@ -293,8 +301,9 @@ func insertAutoReturnIntentRecord(ctx context.Context, data code_data.Provider,
293
301
Source : giftCardIssuedIntent .SendPublicPaymentMetadata .DestinationTokenAccount ,
294
302
Quantity : giftCardIssuedIntent .SendPublicPaymentMetadata .Quantity ,
295
303
296
- IsRemoteSend : true ,
297
- IsReturned : true ,
304
+ IsRemoteSend : true ,
305
+ IsIssuerVoidingGiftCard : isVoidedByUser ,
306
+ IsReturned : ! isVoidedByUser ,
298
307
299
308
OriginalExchangeCurrency : giftCardIssuedIntent .SendPublicPaymentMetadata .ExchangeCurrency ,
300
309
OriginalExchangeRate : giftCardIssuedIntent .SendPublicPaymentMetadata .ExchangeRate ,
0 commit comments