Documentation
¶
Overview ¶
Package journal persists intent lifecycle and signer-global nonces without secrets.
Index ¶
- Constants
- Variables
- type Batch
- type Binding
- type Fill
- type Journal
- func (j *Journal) AdvanceOnchain(id, from, to, hash string) error
- func (j *Journal) BeginOnchain(id, digest, agent string) error
- func (j *Journal) BeginSubmission(r *Record, signer string) (int64, error)
- func (j *Journal) BindOnchainExecution(id, digest string, templates []OnchainTemplate) (string, error)
- func (j *Journal) Blocking(network, account string) ([]*Record, error)
- func (j *Journal) ClaimForBridge(parent string) (*OnchainRecord, error)
- func (j *Journal) Close() error
- func (j *Journal) Create(in trading.Intent) (*Record, bool, error)
- func (j *Journal) CreateOnchain(in OnchainIntent) (*OnchainRecord, error)
- func (j *Journal) CreateSwapOrder(o SwapOrder) (*SwapOrder, error)
- func (j *Journal) FinishSigning(r *Record, signed bool) error
- func (j *Journal) Get(id string) (*Record, error)
- func (j *Journal) GetOnchain(id string) (*OnchainRecord, error)
- func (j *Journal) GetSwapOrder(id string) (*SwapOrder, error)
- func (j *Journal) List() ([]*Record, error)
- func (j *Journal) ListOnchainBridges() ([]*OnchainRecord, error)
- func (j *Journal) ListOnchainSwapChains(agent string) ([]uint64, error)
- func (j *Journal) ListOnchainSwaps(agent string, chain uint64) ([]*OnchainRecord, error)
- func (j *Journal) ListSwapOrders(states ...string) ([]*SwapOrder, error)
- func (j *Journal) Lock() (func(), error)
- func (j *Journal) LockChain(agent string, chain uint64) (func(), error)
- func (j *Journal) LockSwapOrderWatch() (func(), error)
- func (j *Journal) MarkStepHandoff(id string, step int) error
- func (j *Journal) NextNonce(signer string) (int64, error)
- func (j *Journal) Put(r *Record, note string) error
- func (j *Journal) RecordFill(id string, f Fill) error
- func (j *Journal) RecordSwapOrderQuote(id, price, value, at string) (string, error)
- func (j *Journal) RejectDefinite(r *Record, reason string) error
- func (j *Journal) RelayOnchain(id, from, orderID string) error
- func (j *Journal) SetExecutionMode(id, mode string) error
- func (j *Journal) SetOnchainBatch(id, state string, b Batch) error
- func (j *Journal) SkipApproval(id string) error
- func (j *Journal) TransitionSwapOrder(id, from, to string, p SwapOrderPatch) error
- func (j *Journal) Unresolved() ([]*Record, error)
- type OnchainIntent
- type OnchainRecord
- type OnchainTemplate
- type Record
- type Store
- type SwapOrder
- type SwapOrderPatch
- type Transition
Constants ¶
const ( StatePrepared = "prepared" StateCreating = "creating" StateCreated = "created" StateSubmitting = "submitting" StateSigning = "signing" StateSubmitted = "submitted" StateUnknown = "unknown" StateRejected = "rejected" StateAbandoned = "abandoned" )
const ( SwapOrderActive = "active" SwapOrderTriggered = "triggered" SwapOrderExecuting = "executing" SwapOrderFilled = "filled" SwapOrderFailed = "failed" SwapOrderCancelled = "cancelled" )
Swap order states: active -> triggered -> executing -> filled|failed. A triggered order returns to active only when preparing the sell failed before anything was journaled or signed. An executing order returns to active only while its bound sell intent is still prepared (never signed or broadcast); that intent is failed in the same transaction so it can never be submitted later. Otherwise an executing order never sells again. Only an active order can be cancelled.
Variables ¶
var ErrConflict = errors.New("intent id already used with a different payload")
var ErrNotFound = errors.New("intent not found")
var ErrSwapOrderAllConflict = errors.New("another open order already sells all of this token")
ErrSwapOrderAllConflict is returned by CreateSwapOrder when another open order already sells the whole balance of the same agent, chain and token.
var ErrUnresolved = errors.New("account has unresolved submission")
var SwapOrderStates = []string{SwapOrderActive, SwapOrderTriggered, SwapOrderExecuting, SwapOrderFilled, SwapOrderFailed, SwapOrderCancelled}
SwapOrderStates lists every swap order state in lifecycle order.
Functions ¶
This section is empty.
Types ¶
type Batch ¶
type Batch struct {
Nonce uint64 `json:"nonce"`
FromBlock uint64 `json:"from_block"`
TransactionID string `json:"transaction_id,omitempty"`
}
Batch records an atomic wallet_sendCalls execution. Nonce is the agent's confirmed and pending nonce observed before submission: the batch is the agent's transaction at exactly that nonce, which lets status and reconcile find it on chain without a Privy transaction lookup.
type Fill ¶
type Fill struct {
Received string `json:"received"`
Gas string `json:"gas"`
InValue string `json:"in_value,omitempty"`
Source string `json:"source"`
RecordedAt string `json:"recorded_at"`
}
Fill is what a confirmed swap actually delivered, read from its receipts. Received is in raw units of the output token; Gas is the native wei paid by every recorded transaction of the intent. InValue is the oracle native wei value of a token -> token swap's input when the fill was recorded, empty when unpriced or not a token -> token swap.
type Journal ¶
type Journal struct {
// contains filtered or unexported fields
}
func OpenBinding ¶
func (*Journal) AdvanceOnchain ¶
AdvanceOnchain is a durable transition. Hash append commits before receipt polling.
func (*Journal) BeginOnchain ¶
BeginOnchain atomically checks the agent-and-chain unresolved gate and marks the intent sending before any network call. A sending intent must never be replayed.
func (*Journal) BeginSubmission ¶
BeginSubmission atomically commits signer-global nonce and submitting state before signing/sending. The caller must sign only after this returns successfully, and must never retry the action.
func (*Journal) BindOnchainExecution ¶
func (j *Journal) BindOnchainExecution(id, digest string, templates []OnchainTemplate) (string, error)
BindOnchainExecution replaces placeholder templates only while prepared and atomically seals the final, verified transactions under a fresh digest.
func (*Journal) Blocking ¶
Blocking finds possible exposure for the same account across every profile and origin.
func (*Journal) ClaimForBridge ¶
func (j *Journal) ClaimForBridge(parent string) (*OnchainRecord, error)
ClaimForBridge finds the parent's live claim (any state except failed). A failed claim broadcast nothing that could still land (failed is only set before broadcast or on a reverted receipt), so a new claim may follow it; the unique index allows at most one non-failed claim per parent. The destination chain lock must be held while checking and creating a claim.
func (*Journal) CreateOnchain ¶
func (j *Journal) CreateOnchain(in OnchainIntent) (*OnchainRecord, error)
func (*Journal) CreateSwapOrder ¶
CreateSwapOrder stores a new active order. An "all" order is refused with ErrSwapOrderAllConflict while another open "all" order exists for the same agent, chain and token, checked in the same transaction as the insert.
func (*Journal) FinishSigning ¶
FinishSigning atomically advances a verified signature to submitting, or returns an unsent action to created. Nonces remain burned in the nonce table.
func (*Journal) GetOnchain ¶
func (j *Journal) GetOnchain(id string) (*OnchainRecord, error)
func (*Journal) GetSwapOrder ¶
GetSwapOrder loads one order of this profile.
func (*Journal) ListOnchainBridges ¶
func (j *Journal) ListOnchainBridges() ([]*OnchainRecord, error)
ListOnchainBridges returns this profile's bridge records without holding a database cursor while loading individual records.
func (*Journal) ListOnchainSwapChains ¶
ListOnchainSwapChains returns the chains on which agent has swaps that ListOnchainSwaps would return, in ascending order.
func (*Journal) ListOnchainSwaps ¶
func (j *Journal) ListOnchainSwaps(agent string, chain uint64) ([]*OnchainRecord, error)
ListOnchainSwaps returns an agent's confirmed transaction swaps on one chain. Intent swaps are excluded: 'submitted' is terminal for them even when the backend order later expires or refunds, and no fill is journaled. Prepared, in-flight, unknown and failed swaps are excluded too.
func (*Journal) ListSwapOrders ¶
ListSwapOrders returns this profile's orders, oldest first, optionally restricted to the given states.
func (*Journal) Lock ¶
Lock remains compatible with existing callers, but should not span network requests.
func (*Journal) LockChain ¶
LockChain serializes transactions for one agent on one EVM chain across processes.
func (*Journal) LockSwapOrderWatch ¶
LockSwapOrderWatch takes the per-profile watcher lock without waiting, so at most one 'swap orders watch' evaluates and sells this profile's orders.
func (*Journal) MarkStepHandoff ¶
MarkStepHandoff commits before calling Privy. A crash after this point is ambiguous even when no returned hash was persisted.
func (*Journal) RecordFill ¶
RecordFill stores the receipt-derived fill of a confirmed swap once. A second call for the same intent is a no-op that returns ErrConflict.
func (*Journal) RecordSwapOrderQuote ¶
RecordSwapOrderQuote stores the latest price observation of an active order and ratchets the peak value: it only ever increases. It returns the stored peak. A non-active order is left unchanged (ErrConflict).
func (*Journal) RejectDefinite ¶
RejectDefinite persists a submitting record as rejected on the strength of a definite, non-ambiguous RPC rejection (a Connect error code the API client classifies as returned before the handler acted, e.g. invalid_argument or permission_denied) rather than an observed server state. It only applies to a record currently submitting with the same nonce, and the reason is recorded in last_error and the transition note. Ambiguous outcomes must instead be persisted as unknown.
func (*Journal) RelayOnchain ¶
RelayOnchain stores the backend's offchain order identifier and closes the source submission state. A missing response must instead remain unknown.
func (*Journal) SetExecutionMode ¶
SetExecutionMode commits the selected mode before any transaction handoff.
func (*Journal) SetOnchainBatch ¶
SetOnchainBatch durably records batch metadata while the intent is in state. The pre-submission record (nonce, block) must commit before wallet_sendCalls.
func (*Journal) SkipApproval ¶
SkipApproval advances only when a fresh allowance read proves the exact approval is unnecessary. No transaction hash is appended.
func (*Journal) TransitionSwapOrder ¶
func (j *Journal) TransitionSwapOrder(id, from, to string, p SwapOrderPatch) error
TransitionSwapOrder moves an order from one state to another only if it is still in from (compare-and-set). It returns ErrConflict otherwise, which is how a second watcher or a cancel racing a trigger loses.
func (*Journal) Unresolved ¶
type OnchainIntent ¶
type OnchainIntent struct {
ID string `json:"intent_id"`
Kind string `json:"kind"`
Intent bool `json:"intent_based,omitempty"`
ChainID uint64 `json:"chain_id"`
Sender string `json:"sender"`
Recipient string `json:"recipient"`
Token string `json:"token"`
Amount string `json:"amount"`
ResolvedAmount string `json:"resolved_amount,omitempty"`
AmountSource string `json:"amount_source,omitempty"`
Templates []OnchainTemplate `json:"templates"`
OrderID string `json:"order_id,omitempty"`
ParentIntent string `json:"parent_intent,omitempty"`
QuoteID string `json:"quote_id,omitempty"`
Generation int32 `json:"generation,omitempty"`
Route string `json:"route,omitempty"`
Target string `json:"target,omitempty"`
Spender string `json:"spender,omitempty"`
OutToken string `json:"out_token,omitempty"`
OutChain uint64 `json:"out_chain,omitempty"`
MinOut string `json:"min_out,omitempty"`
ExpiresAt string `json:"expires_at,omitempty"`
CreatedAt string `json:"created_at"`
}
OnchainIntent binds every economic field and every ordered transaction template.
func (OnchainIntent) Digest ¶
func (in OnchainIntent) Digest() string
type OnchainRecord ¶
type OnchainRecord struct {
OnchainIntent
Digest string `json:"digest"`
State string `json:"state"`
Hashes []string `json:"tx_hashes"`
Batch *Batch `json:"batch,omitempty"`
NextStep string `json:"next_step,omitempty"`
ExecutionMode string `json:"execution_mode,omitempty"`
StepIndex int `json:"step_index,omitempty"`
StepInFlight bool `json:"step_in_flight,omitempty"`
ApprovalSkipped bool `json:"approval_skipped,omitempty"`
BackendOrderID string `json:"backend_order_id,omitempty"`
Fill *Fill `json:"fill,omitempty"`
UpdatedAt string `json:"updated_at"`
}
type OnchainTemplate ¶
type OnchainTemplate struct {
ChainID uint64 `json:"chain_id"`
To string `json:"to"`
Data string `json:"data"`
Value string `json:"value"`
Token string `json:"token,omitempty"`
Amount string `json:"amount,omitempty"`
Decimals int `json:"decimals,omitempty"`
Spender string `json:"spender,omitempty"`
}
type Record ¶
type Record struct {
Intent trading.Intent `json:"intent"`
Digest string `json:"digest"`
State string `json:"state"`
ActionID string `json:"action_id,omitempty"`
ActionJSON string `json:"action_json,omitempty"`
Cloid string `json:"cloid,omitempty"`
Nonce int64 `json:"nonce,omitempty"`
ServerState string `json:"server_state,omitempty"`
OrderID int64 `json:"order_id,omitempty"`
LastError string `json:"last_error,omitempty"`
UpdatedAt string `json:"updated_at"`
History []Transition `json:"history"`
}
func (*Record) Unresolved ¶
Unresolved reports whether a record still needs reconciliation.
type Store ¶
type Store interface {
Create(trading.Intent) (*Record, bool, error)
Get(string) (*Record, error)
Put(*Record, string) error
List() ([]*Record, error)
Unresolved() ([]*Record, error)
NextNonce(string) (int64, error)
BeginSubmission(*Record, string) (int64, error)
Blocking(string, string) ([]*Record, error)
Close() error
}
Store is the durable journal interface. Operations are short transactions, never network-spanning.
type SwapOrder ¶
type SwapOrder struct {
ID string `json:"order_id"`
Agent string `json:"agent"`
ChainID uint64 `json:"chain_id"`
Token string `json:"token"`
Decimals int `json:"decimals"`
Amount string `json:"amount"`
Size string `json:"size"`
TakeProfitPct string `json:"take_profit_pct,omitempty"`
StopLossPct string `json:"stop_loss_pct,omitempty"`
TrailingStopPct string `json:"trailing_stop_pct,omitempty"`
SlippageBps int `json:"slippage_bps"`
Basis string `json:"basis,omitempty"`
BasisSource string `json:"basis_source"`
State string `json:"state"`
PeakValue string `json:"peak_value,omitempty"`
LastPrice string `json:"last_price,omitempty"`
LastValue string `json:"last_value,omitempty"`
LastQuoteAt string `json:"last_quote_at,omitempty"`
Trigger string `json:"trigger,omitempty"`
SellIntentID string `json:"sell_intent_id,omitempty"`
NeedsReconcile bool `json:"needs_reconcile"`
LastError string `json:"last_error,omitempty"`
Attempts int `json:"attempts"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
SwapOrder is a client-side exit (token -> native) for an EVM swap position. Values are native-denominated decimals; percentages are decimal strings.
type SwapOrderPatch ¶
type SwapOrderPatch struct {
Trigger *string
SellIntentID *string
LastError *string
NeedsReconcile *bool
// CountAttempt increments the failed-sell-attempt counter.
CountAttempt bool
}
SwapOrderPatch sets optional fields during a state transition.