Atomic Sale
Set Atomic Mode
Switch a market’s liquidation router between atomic and two-step settlement
POST
/
lending-external-securities-v2
/
api
/
liquidations
/
{marketId}
/
atomic-mode
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/{marketId}/atomic-mode" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"mode": 1}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/liquidations/${marketId}/atomic-mode`;
const headers = { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' };
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify({ mode: 1 }) });
const { success, data, error } = await res.json();
if (!success) throw new Error(`${error.code}: ${error.message}`);
if (data.alreadySet) return;
if (data.warnings.some((w: { code: string }) => w.code === 'ATOMIC_BUYER_UNAVAILABLE')) {
throw new Error('The sale recipient cannot buy yet');
}
const tx = await routerAdminWallet.sendTransaction(data.transaction);
await tx.wait();
await fetch(url, { method: 'POST', headers, body: JSON.stringify({ txHash: tx.hash }) });
{
"success": true,
"data": {
"success": true,
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"chainId": 11155111,
"value": "0"
},
"functionName": "setAtomicMode",
"description": "Switch the liquidation router to atomic mode: a liquidation sells the seized collateral to the sale recipient at its standing bid and settles in the same transaction, or reverts.",
"requiredRole": "DEFAULT_ADMIN_ROLE",
"signer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"mode": 1,
"modeName": "ATOMIC",
"previousMode": 0,
"routerAddress": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"atomic": {
"marketId": "cmuvtwr29002ds2mft47ye2yl",
"available": true,
"mode": 0,
"modeName": "TWO_STEP",
"effective": false,
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"buyerAvailable": true,
"code": null,
"reasonCode": null
},
"warnings": [
{
"code": "SELF_PURCHASE_TWO_STEP_ONLY",
"message": "The sale recipient's own loans can only be liquidated in two-step mode."
}
],
"confirmWith": {
"endpoint": "POST /lending-external-securities-v2/api/liquidations/cmuvtwr29002ds2mft47ye2yl/atomic-mode",
"field": "txHash",
"body": { "txHash": null }
}
}
}
{
"success": true,
"data": {
"txHash": "0x4a7c1e9f3b5d02e68c1a4f7b9d3e05c28a6f1b4d7e9c2a05f3b8d6e1a4c7f9b2",
"signedBy": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"mode": 1,
"modeName": "ATOMIC",
"currentMode": 1,
"currentModeName": "ATOMIC",
"routerAddress": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf"
}
}
{
"success": false,
"error": {
"code": "ATOMIC_SALE_UNAVAILABLE",
"message": "This market prices its collateral from a fixed price set at deployment, which is neither a stock-exchange nor a market price, so the free-hand sale under § 1259 BGB, which the atomic sale carries out, is not available on it. Liquidations stay two-step and realize through the path its adoption terms declare.",
"txHash": null,
"details": {
"priceSource": "FIXED",
"realizationMode": "ISSUER_REDEMPTION",
"reasonCode": "PRICE_SOURCE_NOT_MARKET"
}
}
}
Builds the
When the router already runs the requested mode, nothing is built: the answer carries
Confirming with
setAtomicMode transaction on the market’s liquidation router, or confirms it with txHash. The wallet holding DEFAULT_ADMIN_ROLE on the router signs. In atomic mode (1) a liquidation sells the seized collateral to the sale recipient at its standing bid and settles the record in the same transaction, or reverts. In two-step mode (0) seized collateral waits on the router for the sale desk. Every router starts in two-step mode.
In atomic mode a liquidation succeeds only while the sale recipient can buy. Without a live bid, enough allowance and balance, or a fresh price, every liquidation reverts and loans stay liquidatable, also loans the pool is losing money on. Read the state with Get Atomic Sale before switching, and switch back to two-step when the sale recipient stops bidding.
When atomic mode is refused
Switching atomic mode on is refused with409 ATOMIC_SALE_UNAVAILABLE unless the market’s price source is MARKET and its lender of record declared EXCHANGE_SALE as its realization mode. details.reasonCode is PRICE_SOURCE_NOT_MARKET or REALIZATION_PATH_NOT_EXCHANGE_SALE, with priceSource and realizationMode beside it. When the price source, or the realization path a MARKET market declared, cannot be read, the call answers 503 MARKET_STATE_UNAVAILABLE. Switching back to two-step is never refused on this ground.
A router whose implementation predates the atomic sale is refused with 409 ATOMIC_UNSUPPORTED, and details.routerUpgrade carries its upgrade status. The router administrator upgrades it first.
Path Parameters
string
required
Body Parameters
integer
1 atomic or 0 two-step. Required when building calldata.string
The router administrator that will sign. Omit it to check your instance’s primary verified wallet. The wallet must hold
DEFAULT_ADMIN_ROLE on the router, or the call is refused with ROUTER_ADMIN_ROLE_MISSING.string
Hash of the mined transaction. Send it to confirm;
mode is then read from the router’s AtomicModeSet event. Omit it to receive the calldata.Response Fields
The calldata response:object
Show child attributes
Show child attributes
string
SIGN_TRANSACTION.object
The
setAtomicMode call on the router, { to, data, chainId, value }.string
setAtomicMode.string
What the new mode does, in words.
string
DEFAULT_ADMIN_ROLE.string
The wallet that holds the role.
integer
The mode requested.
string
ATOMIC or TWO_STEP.integer
The mode the router holds now.
string
The router, lowercased.
object
The atomic sale state as on Get Atomic Sale, without
saleBasis and saleRecipientLenderSide. Its available, reasonCode and reason describe the router, the market and the sale recipient, and leave the sale basis out.array
{ code, message } entries when switching to atomic mode. See Warnings. Empty when switching to two-step.object
{ endpoint, field, body }: this route, txHash as the field.alreadySet: true, mode, modeName, routerAddress and atomic.
The confirmed response carries txHash, signedBy, mode and modeName as the transaction set them, currentMode and currentModeName as the router answers now, and routerAddress. The change is written to the audit log as LENDING_ATOMIC_MODE_SET. The calldata example below shortens atomic.
Warnings
code | When |
|---|---|
MARKET_UPGRADE_REQUIRED | The market runs an implementation without the atomic sale, so liquidations stay two-step even in atomic mode until the market is upgraded |
DUTCH_AUCTIONS_ON | The market opens Dutch auctions, which take precedence: liquidations keep opening auctions instead of selling atomically. The remainder of an expired auction reaches the router two-step, and Sell Pending Liquidation can sell it |
ATOMIC_BUYER_UNAVAILABLE | The sale recipient cannot buy now, so every atomic liquidation would revert. Carries reasonCode |
ATOMIC_BUYER_UNVERIFIED | Whether the sale recipient can buy could not be read |
SELF_PURCHASE_TWO_STEP_ONLY | Always on atomic mode. The sale recipient’s own loans can be liquidated only in two-step mode |
SALE_RECIPIENT_LENDER_SIDE | The sale recipient is also the lender of record, collateral agent, liquidation operator, controller or router administrator. Carries roles. See Get Atomic Sale |
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/{marketId}/atomic-mode" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"mode": 1}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/liquidations/${marketId}/atomic-mode`;
const headers = { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' };
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify({ mode: 1 }) });
const { success, data, error } = await res.json();
if (!success) throw new Error(`${error.code}: ${error.message}`);
if (data.alreadySet) return;
if (data.warnings.some((w: { code: string }) => w.code === 'ATOMIC_BUYER_UNAVAILABLE')) {
throw new Error('The sale recipient cannot buy yet');
}
const tx = await routerAdminWallet.sendTransaction(data.transaction);
await tx.wait();
await fetch(url, { method: 'POST', headers, body: JSON.stringify({ txHash: tx.hash }) });
{
"success": true,
"data": {
"success": true,
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"chainId": 11155111,
"value": "0"
},
"functionName": "setAtomicMode",
"description": "Switch the liquidation router to atomic mode: a liquidation sells the seized collateral to the sale recipient at its standing bid and settles in the same transaction, or reverts.",
"requiredRole": "DEFAULT_ADMIN_ROLE",
"signer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"mode": 1,
"modeName": "ATOMIC",
"previousMode": 0,
"routerAddress": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"atomic": {
"marketId": "cmuvtwr29002ds2mft47ye2yl",
"available": true,
"mode": 0,
"modeName": "TWO_STEP",
"effective": false,
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"buyerAvailable": true,
"code": null,
"reasonCode": null
},
"warnings": [
{
"code": "SELF_PURCHASE_TWO_STEP_ONLY",
"message": "The sale recipient's own loans can only be liquidated in two-step mode."
}
],
"confirmWith": {
"endpoint": "POST /lending-external-securities-v2/api/liquidations/cmuvtwr29002ds2mft47ye2yl/atomic-mode",
"field": "txHash",
"body": { "txHash": null }
}
}
}
{
"success": true,
"data": {
"txHash": "0x4a7c1e9f3b5d02e68c1a4f7b9d3e05c28a6f1b4d7e9c2a05f3b8d6e1a4c7f9b2",
"signedBy": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"mode": 1,
"modeName": "ATOMIC",
"currentMode": 1,
"currentModeName": "ATOMIC",
"routerAddress": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf"
}
}
{
"success": false,
"error": {
"code": "ATOMIC_SALE_UNAVAILABLE",
"message": "This market prices its collateral from a fixed price set at deployment, which is neither a stock-exchange nor a market price, so the free-hand sale under § 1259 BGB, which the atomic sale carries out, is not available on it. Liquidations stay two-step and realize through the path its adoption terms declare.",
"txHash": null,
"details": {
"priceSource": "FIXED",
"realizationMode": "ISSUER_REDEMPTION",
"reasonCode": "PRICE_SOURCE_NOT_MARKET"
}
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | mode is not 0 or 1, neither mode nor txHash was sent, or an address or hash is malformed |
NO_MARKET_ADDRESS | 400 | The market has no on-chain address recorded |
MISSING_MARKET_ID | 400 | marketId is longer than 100 characters |
ROUTER_ADMIN_ROLE_MISSING | 400 | The signer does not hold DEFAULT_ADMIN_ROLE on the router |
WALLET_NOT_CONFIGURED | 400 | No signerAddress was sent and your instance has no verified wallet |
TX_NOT_VERIFIED | 400 | The confirmed transaction set no atomic mode on this market’s router |
ATOMIC_MODE_FAILED | 400 | The change could not be prepared or confirmed and no more specific code applied |
MARKET_NOT_FOUND | 404 | No market with this ID on your instance. See Market IDs |
ATOMIC_SALE_UNAVAILABLE | 409 | Atomic mode was requested on a market that is not MARKET-priced, or whose realization mode is not EXCHANGE_SALE. details carries priceSource, realizationMode and reasonCode. Keep the market two-step |
ATOMIC_UNSUPPORTED | 409 | The router’s implementation predates the atomic sale. details carries routerAddress and routerUpgrade |
MARKET_STATE_UNAVAILABLE | 503 | The market’s price source, or the realization path a MARKET market declared, could not be read. Nothing was signed. Retry shortly |
ROUTER_UNREADABLE | 503 | The router, or its current mode, could not be read. Retry shortly |
ROUTER_UNRESOLVED | 503 | The market’s liquidation router could not be read. Retry shortly |
ROLE_UNVERIFIABLE | 503 | The signer’s role on the router could not be read. Retry shortly |
txHash can also return any transaction verification error.⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/{marketId}/atomic-mode" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"mode": 1}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/liquidations/${marketId}/atomic-mode`;
const headers = { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' };
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify({ mode: 1 }) });
const { success, data, error } = await res.json();
if (!success) throw new Error(`${error.code}: ${error.message}`);
if (data.alreadySet) return;
if (data.warnings.some((w: { code: string }) => w.code === 'ATOMIC_BUYER_UNAVAILABLE')) {
throw new Error('The sale recipient cannot buy yet');
}
const tx = await routerAdminWallet.sendTransaction(data.transaction);
await tx.wait();
await fetch(url, { method: 'POST', headers, body: JSON.stringify({ txHash: tx.hash }) });
{
"success": true,
"data": {
"success": true,
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"chainId": 11155111,
"value": "0"
},
"functionName": "setAtomicMode",
"description": "Switch the liquidation router to atomic mode: a liquidation sells the seized collateral to the sale recipient at its standing bid and settles in the same transaction, or reverts.",
"requiredRole": "DEFAULT_ADMIN_ROLE",
"signer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"mode": 1,
"modeName": "ATOMIC",
"previousMode": 0,
"routerAddress": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"atomic": {
"marketId": "cmuvtwr29002ds2mft47ye2yl",
"available": true,
"mode": 0,
"modeName": "TWO_STEP",
"effective": false,
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"buyerAvailable": true,
"code": null,
"reasonCode": null
},
"warnings": [
{
"code": "SELF_PURCHASE_TWO_STEP_ONLY",
"message": "The sale recipient's own loans can only be liquidated in two-step mode."
}
],
"confirmWith": {
"endpoint": "POST /lending-external-securities-v2/api/liquidations/cmuvtwr29002ds2mft47ye2yl/atomic-mode",
"field": "txHash",
"body": { "txHash": null }
}
}
}
{
"success": true,
"data": {
"txHash": "0x4a7c1e9f3b5d02e68c1a4f7b9d3e05c28a6f1b4d7e9c2a05f3b8d6e1a4c7f9b2",
"signedBy": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"mode": 1,
"modeName": "ATOMIC",
"currentMode": 1,
"currentModeName": "ATOMIC",
"routerAddress": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf"
}
}
{
"success": false,
"error": {
"code": "ATOMIC_SALE_UNAVAILABLE",
"message": "This market prices its collateral from a fixed price set at deployment, which is neither a stock-exchange nor a market price, so the free-hand sale under § 1259 BGB, which the atomic sale carries out, is not available on it. Liquidations stay two-step and realize through the path its adoption terms declare.",
"txHash": null,
"details": {
"priceSource": "FIXED",
"realizationMode": "ISSUER_REDEMPTION",
"reasonCode": "PRICE_SOURCE_NOT_MARKET"
}
}
}
