Querying a position
Find a user's Spot Margin positions through the Leaser, then read a position's state, amounts due, interest rates and close policy from its Lease.
Every position is its own Lease contract with public state, so an app, a bot or an indexer can follow it with two queries. The Leaser lists the positions that a user holds, and each Lease reports its current state, the amounts due and any operation in progress.
Find a user's positions
The Leaser keeps a registry of positions for each user, and its leases
query returns the ones that a given account owns:
nolusd q wasm contract-state smart $LEASER '{"leases":{"owner":"<nolus account>"}}' -o json
# {"data":["nolus1...","nolus1..."]}Replace <nolus account> with the user's Nolus account, and set $LEASER to
the address of the protocol's Leaser. As the comment under the command shows,
the response is the list of Lease addresses that the account owns in that
protocol. Because each protocol has its own Leaser, cover every market by
querying the Leaser of each protocol, whose addresses you can look up as
described in
Find the contract addresses.
Read a position
A position's state comes from the state query on its Lease, which you can
send as it is or with a projection of the amounts due:
nolusd q wasm contract-state smart <lease> '{"state":{}}'
nolusd q wasm contract-state smart <lease> '{"state":{"due_projection_secs":400}}'Replace <lease> with the address of the position's Lease contract. The
optional due_projection_secs projects the amounts due that many seconds
ahead, which helps when you plan to repay in full a few minutes from now,
since a repayment covers the interest accrued until it executes.
Position states
The response holds exactly one of these states:
| State | Meaning | Fields |
|---|---|---|
opening | The position is being opened, which covers the account on Solana, its funding and the swap. | currency, downpayment, loan, loan_interest_rate, in_progress (open_lease, transfer_out, buy_asset) |
opened | The position is open. It can be repaid, closed or liquidated. | See the table below. |
paid | The debt is fully repaid. The position asset is returning to the escrow of Solray, the Nolus program on Solana, and a receipt for it is being credited to the user's Nolus account. | amount, in_progress (transfer_in_init, transfer_in_finish) |
closing | The debt is settled and the account on Solana is being closed. | none |
closed | Final. The position was repaid or closed and the user has been paid. | none |
liquidated | Final. The position was fully liquidated. | none |
open_failed | Final. The account on Solana could not be opened, so the down payment was refunded and the loan closed. | reason |
The paid and closing states complete on their own, so nothing needs to be
sent to finish them.
Fields of an open position
An opened state carries the size, the rates and the amounts due of the
position, as in this abbreviated response for a SOL long:
{
"data": {
"opened": {
"amount": { "amount": "4747215219", "ticker": "SOL" },
"loan_interest_rate": 96,
"margin_interest_rate": 45,
"principal_due": { "amount": "400000000", "ticker": "USDC" },
"overdue_margin": { "amount": "0", "ticker": "USDC" },
"overdue_interest": { "amount": "0", "ticker": "USDC" },
"overdue_collect_in": 2331538356788423,
"due_margin": { "amount": "148665", "ticker": "USDC" },
"due_interest": { "amount": "317152", "ticker": "USDC" },
"due_projection_ns": 0,
"close_policy": { "take_profit": null, "stop_loss": null },
"validity": "1792413422681210136",
"status": "idle"
}
}
}Each field of the opened state means the following:
| Field | Meaning |
|---|---|
amount | The position size in the position asset, held in the account on Solana. |
loan_interest_rate | The loan rate, fixed at opening, in permille a year. |
margin_interest_rate | The margin interest rate, in permille a year. |
principal_due | Loan principal still owed, in the pool currency. |
overdue_interest, overdue_margin | Loan and margin interest unpaid past the due period. |
overdue_collect_in | Nanoseconds until unpaid interest becomes overdue and is collected by a partial liquidation. |
due_interest, due_margin | Loan and margin interest accrued in the current due period. |
due_projection_ns | The projection requested with due_projection_secs, in nanoseconds, or 0. |
close_policy | Take profit and stop loss levels as LTV in permille, or null when not set. |
validity | The block time, in nanoseconds since the Unix epoch, the amounts were computed for. |
status | idle, slippage_protection_activated, or in_progress with the running operation. |
For an open position, the
LTV is its
total due divided by the value of amount in the pool currency at the oracle
price, where the total due is the principal plus the four interest amounts. To convert the amounts, the
oracle's {"currencies":{}} query gives the decimal_digits of each ticker.
Status values
The status field shows whether an operation is running on the position, and
it takes one of these values:
status | Meaning |
|---|---|
idle | Nothing in progress. |
in_progress with repayment | A repayment in a currency other than the pool currency is being swapped on Solana. |
in_progress with close | A full or partial close is selling the position asset. |
in_progress with liquidation | A liquidation is running, with cause set to liability when LTV is too high or to overdue when interest is past due. |
slippage_protection_activated | A liquidation swap would have filled below the oracle price minus the liquidation slippage limit, so it did not execute. The position waits until it is re-assessed. |
While an operation is in progress, or while slippage protection is active,
the Lease rejects any new repay, close or close policy change on the same
position. Retry such a request once status is back to idle.
Once you know the state of a position, Repaying and closing explains how to repay it, close it and set its take profit and stop loss.
Opening a position
Send open_lease to open a Spot Margin position, see how the fixed loan rate is set, and follow the Lease as it builds its account on Solana.
Repaying and closing
Repay a Spot Margin position, close it in full or in part, and set take profit and stop loss, with the order in which payments and liquidations apply.