File tree Expand file tree Collapse file tree
main/kotlin/com/getcode/opencode
internal/domain/repositories
test/kotlin/com/getcode/opencode/model/core/errors Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -12,6 +12,7 @@ import com.getcode.opencode.model.transactions.SwapFundingSource
1212import com.getcode.opencode.model.transactions.SwapRequest
1313import com.getcode.opencode.model.transactions.TransactionMetadata
1414import com.getcode.opencode.model.transactions.WithdrawalAvailability
15+ import com.getcode.opencode.model.core.errors.SubmitIntentError
1516import com.getcode.opencode.repositories.TransactionRepository
1617import com.getcode.opencode.solana.intents.IntentType
1718import com.getcode.solana.keys.Mint
@@ -29,7 +30,12 @@ internal class InternalTransactionRepository @Inject constructor(
2930 intent : IntentType ,
3031 owner : Ed25519 .KeyPair
3132 ): Result <IntentType > = service.submitIntent(scope, intent, owner)
32- .onFailure { ErrorUtils .handleError(it) }
33+ .onFailure {
34+ // Expected race: pre-claim check passes but the gift card is claimed
35+ // before the intent is submitted. Not a bug — skip Bugsnag reporting.
36+ if (it is SubmitIntentError .StaleState && it.isGiftCardAlreadyClaimed) return @onFailure
37+ ErrorUtils .handleError(it)
38+ }
3339
3440 override suspend fun getIntentMetadata (
3541 intentId : PublicKey ,
Original file line number Diff line number Diff line change @@ -122,7 +122,10 @@ sealed class SubmitIntentError(
122122 if (details.isNotEmpty()) append(" : ${details.joinToString()} " )
123123 }), NotifiableError
124124 data class StaleState (private val reasons : List <String >) :
125- SubmitIntentError (message = reasons.joinToString()), NotifiableError
125+ SubmitIntentError (message = reasons.joinToString()), NotifiableError {
126+ val isGiftCardAlreadyClaimed: Boolean
127+ get() = reasons.any { it.contains(" gift card balance has already been claimed" ) }
128+ }
126129
127130 data class Denied (private val reasons : List <String >) :
128131 SubmitIntentError (message = reasons.joinToString())
Original file line number Diff line number Diff line change @@ -6,6 +6,7 @@ import com.codeinc.opencode.gen.transaction.v1.reasonStringErrorDetails
66import com.codeinc.opencode.gen.transaction.v1.deniedErrorDetails
77import kotlin.test.Test
88import kotlin.test.assertEquals
9+ import kotlin.test.assertFalse
910import kotlin.test.assertIs
1011import kotlin.test.assertTrue
1112
@@ -146,6 +147,30 @@ class SubmitIntentErrorTest {
146147 errors.forEach { assertTrue(it is Throwable ) }
147148 }
148149
150+ @Test
151+ fun staleStateWithGiftCardClaimedReasonIsGiftCardAlreadyClaimed () {
152+ val error = SubmitIntentError .typed(
153+ buildError(
154+ SubmitIntentResponse .Error .Code .STALE_STATE ,
155+ reasonStrings = listOf (" gift card balance has already been claimed" )
156+ )
157+ )
158+ assertIs<SubmitIntentError .StaleState >(error)
159+ assertTrue(error.isGiftCardAlreadyClaimed)
160+ }
161+
162+ @Test
163+ fun staleStateWithOtherReasonIsNotGiftCardAlreadyClaimed () {
164+ val error = SubmitIntentError .typed(
165+ buildError(
166+ SubmitIntentResponse .Error .Code .STALE_STATE ,
167+ reasonStrings = listOf (" nonce expired" )
168+ )
169+ )
170+ assertIs<SubmitIntentError .StaleState >(error)
171+ assertFalse(error.isGiftCardAlreadyClaimed)
172+ }
173+
149174 @Test
150175 fun otherWrausesCause () {
151176 val cause = RuntimeException (" root cause" )
You can’t perform that action at this time.
0 commit comments