Class: Solrengine::Sdp::TokenMint
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Solrengine::Sdp::TokenMint
- Defined in:
- app/models/solrengine/sdp/token_mint.rb
Overview
Engine-owned record of every mint attempted through SDP — the audit trail and the never-double-mint guard.
Status machine:
minting → just recorded, not yet sent (created before the POST)
in_flight → claimed by MintJob; the POST is being sent (atomic claim
so a crash + queue-retry never re-sends the same mint)
minted → confirmed on-chain (terminal)
failed → SDP rejected it, or it was never sent (terminal)
unknown → the POST read-timed out: outcome uncertain. NEVER re-sent
(double-mint risk), and SDP exposes no mint-transaction
listing to reconcile against — surfaced for manual review.
The mint POST is NEVER retried (SDP has no idempotency key). Unlike a Transfer there is no memo-token reconcile path (no list endpoint for mint transactions), so a timed-out mint stays ‘unknown` rather than auto-resolving.
Constant Summary collapse
- MEMO_TOKEN_PREFIX =
"sdpmint-"- MEMO_SEPARATOR =
" | "- STATUSES =
%w[minting in_flight minted failed unknown].freeze
- TERMINAL_STATUSES =
%w[minted failed unknown].freeze
Instance Method Summary collapse
-
#claim! ⇒ Object
Atomic claim: minting → in_flight in one UPDATE.
- #composed_memo ⇒ Object
- #pending? ⇒ Boolean
-
#submit_to_sdp! ⇒ Object
The single, never-retried mint POST.
Instance Method Details
#claim! ⇒ Object
Atomic claim: minting → in_flight in one UPDATE. Returns true only for the caller that won the claim, so a crash + queue-retry (or two workers) can never send the same mint twice. A row stuck in_flight is a crashed-mid-send and is left for manual reconcile, never auto-re-sent.
48 49 50 51 52 |
# File 'app/models/solrengine/sdp/token_mint.rb', line 48 def claim! won = self.class.where(id: id, status: "minting").update_all(status: "in_flight", updated_at: Time.current) reload if won == 1 won == 1 end |
#composed_memo ⇒ Object
81 82 83 |
# File 'app/models/solrengine/sdp/token_mint.rb', line 81 def composed_memo [ memo, memo_token ].compact.join(MEMO_SEPARATOR) end |
#pending? ⇒ Boolean
40 41 42 |
# File 'app/models/solrengine/sdp/token_mint.rb', line 40 def pending? %w[minting in_flight].include?(status) end |
#submit_to_sdp! ⇒ Object
The single, never-retried mint POST. Every outcome lands on the row.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'app/models/solrengine/sdp/token_mint.rb', line 55 def submit_to_sdp! tx = Solrengine::Sdp.client.mint_token( token.sdp_token_id, signing_wallet_id: token.signing_wallet_id, destination: destination, amount: amount, memo: composed_memo ) update!( status: terminal_for(tx.status), signature: tx.signature, sdp_transaction_id: tx.id, token_account: tx.token_account, sdp_error: tx.error, settled_at: Time.current ) rescue ::Sdp::Timeout # Outcome unknown — NEVER re-send. No mint-tx listing to reconcile. update!(status: "unknown") rescue ::Sdp::Unavailable => e # Request never processed — safe to mark failed (no money moved). update!(status: "failed", sdp_error: "unsent: #{e.}", settled_at: Time.current) rescue ::Sdp::Error => e update!(status: "failed", sdp_error: e., settled_at: Time.current) end |