Liquidation Bots
Connect Bot to Market
Build the transactions that connect a liquidation bot to a market or disconnect it
POST
/
lending-external-securities-v2
/
api
/
liquidation-bots
/
{botId}
/
connect
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidation-bots/{botId}/connect" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"marketId": "clx_secmarket_001", "connect": true}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/liquidation-bots/${botId}/connect`,
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ marketId, connect: true })
}
);
const { data } = await res.json();
if (!data.alreadyInState) {
for (const step of data.steps) {
const signer = step.authority === 'BOT_OWNER' ? botOwnerWallet : marketAdminWallet;
const tx = await signer.sendTransaction(step.transaction);
await tx.wait();
}
}
{
"success": true,
"data": {
"action": "SIGN_TRANSACTIONS",
"steps": [
{
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xc40dea7387a290e7ce71784a65ae0ed6bb1ae555",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "setMarketEnabled",
"description": "Allow the bot to act on NYF1",
"authority": "BOT_OWNER"
},
{
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "grantRole",
"description": "Grant the bot the liquidator role on the market",
"authority": "MARKET_ADMIN"
}
],
"confirmStepIndex": 1,
"functionName": "connectMarket",
"marketId": "clx_secmarket_001",
"marketAddress": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"confirmWith": { "endpoint": "confirm-tx", "txHash": true }
},
"error": null,
"metadata": {
"timestamp": "2026-09-20T10:10:00.000Z",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"instanceId": "inst_abc123"
}
}
{
"success": true,
"data": {
"success": true,
"alreadyInState": true,
"connected": true,
"marketId": "clx_secmarket_001"
}
}
{
"success": false,
"data": null,
"error": {
"code": "CHAIN_READ_FAILED",
"message": "The bot or the market could not be read just now, so no step is offered. Retry in a moment."
}
}
Builds the transactions that connect a bot to one of the instance’s markets, or disconnect it. A connection has two halves held by two parties, so the answer can hold two steps for two different signers. The API reads both halves first and returns only the ones not already in the requested state.
Trusset holds no key and signs neither step. The bot step comes first in both directions. The two are independent transactions, so neither has to be mined before the other. Either half alone stops the bot acting on a market, and the bot step is the one the owner can take without the market admin.
A market still seeking a lender of record has no market admin, so its market step cannot succeed. This call does not check for that. A lender of record can instead grant the role while taking it, by naming the bot as
Confirming a step is optional. The connection is read from the chain every time, and confirming only clears the cached read so Get Liquidation Bot shows the change at once.
| Half | Transaction | Signer, as authority |
|---|---|---|
| Bot side | setMarketEnabled(market, true) or false, on the bot | BOT_OWNER: the bot’s owner wallet |
| Market side | grantRole or revokeRole of LIQUIDATOR_ROLE for the bot, on the market | MARKET_ADMIN: the market admin, holder of DEFAULT_ADMIN_ROLE on the market |
liquidator on Accept Lender Role. Set Liquidator Role grants it too.
Path Parameters
string
required
Bot ID.
Body Parameters
string
required
ID of one of your instance’s markets, 1 to 100 characters. The market must have an on-chain address.
boolean
required
true to connect, false to disconnect.Response Fields
When both halves already match the request,data is { success: true, alreadyInState: true, connected, marketId } and there is nothing to sign. Otherwise:
object
Show child attributes
Show child attributes
string
SIGN_TRANSACTIONS.array
One or two transactions, the bot step first.
Show child attributes
Show child attributes
string
SIGN_TRANSACTION.object
Unsigned call:
to is the bot for the bot step and the market for the market step, plus data, value ("0") and chainId.string
setMarketEnabled on the bot step, grantRole or revokeRole on the market step.string
What the step does.
string
BOT_OWNER or MARKET_ADMIN, the party that must sign.integer
Index of the last step. Its mined hash is the one to send to Confirm Bot Transaction.
string
connectMarket or disconnectMarket. A label for the operation, not a contract function.string
Market ID.
string
Market contract address.
object
{ "endpoint": "confirm-tx", "txHash": true }. See Confirm Bot Transaction.curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidation-bots/{botId}/connect" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"marketId": "clx_secmarket_001", "connect": true}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/liquidation-bots/${botId}/connect`,
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ marketId, connect: true })
}
);
const { data } = await res.json();
if (!data.alreadyInState) {
for (const step of data.steps) {
const signer = step.authority === 'BOT_OWNER' ? botOwnerWallet : marketAdminWallet;
const tx = await signer.sendTransaction(step.transaction);
await tx.wait();
}
}
{
"success": true,
"data": {
"action": "SIGN_TRANSACTIONS",
"steps": [
{
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xc40dea7387a290e7ce71784a65ae0ed6bb1ae555",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "setMarketEnabled",
"description": "Allow the bot to act on NYF1",
"authority": "BOT_OWNER"
},
{
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "grantRole",
"description": "Grant the bot the liquidator role on the market",
"authority": "MARKET_ADMIN"
}
],
"confirmStepIndex": 1,
"functionName": "connectMarket",
"marketId": "clx_secmarket_001",
"marketAddress": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"confirmWith": { "endpoint": "confirm-tx", "txHash": true }
},
"error": null,
"metadata": {
"timestamp": "2026-09-20T10:10:00.000Z",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"instanceId": "inst_abc123"
}
}
{
"success": true,
"data": {
"success": true,
"alreadyInState": true,
"connected": true,
"marketId": "clx_secmarket_001"
}
}
{
"success": false,
"data": null,
"error": {
"code": "CHAIN_READ_FAILED",
"message": "The bot or the market could not be read just now, so no step is offered. Retry in a moment."
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | marketId is missing, empty or longer than 100 characters, or connect is not a boolean |
BOT_NOT_FOUND | 404 | No bot with this ID belongs to your instance |
MARKET_NOT_FOUND | 404 | No market with this ID belongs to your instance, or it has no on-chain address |
BOT_NOT_DEPLOYED | 409 | The bot record has no contract address |
CHAIN_READ_FAILED | 503 | The bot or the market could not be read, so no step is offered. Retry |
BOT_CONNECT_FAILED | 500 | An unexpected failure. The message is generic; retry |
⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidation-bots/{botId}/connect" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"marketId": "clx_secmarket_001", "connect": true}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/liquidation-bots/${botId}/connect`,
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ marketId, connect: true })
}
);
const { data } = await res.json();
if (!data.alreadyInState) {
for (const step of data.steps) {
const signer = step.authority === 'BOT_OWNER' ? botOwnerWallet : marketAdminWallet;
const tx = await signer.sendTransaction(step.transaction);
await tx.wait();
}
}
{
"success": true,
"data": {
"action": "SIGN_TRANSACTIONS",
"steps": [
{
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xc40dea7387a290e7ce71784a65ae0ed6bb1ae555",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "setMarketEnabled",
"description": "Allow the bot to act on NYF1",
"authority": "BOT_OWNER"
},
{
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "grantRole",
"description": "Grant the bot the liquidator role on the market",
"authority": "MARKET_ADMIN"
}
],
"confirmStepIndex": 1,
"functionName": "connectMarket",
"marketId": "clx_secmarket_001",
"marketAddress": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"confirmWith": { "endpoint": "confirm-tx", "txHash": true }
},
"error": null,
"metadata": {
"timestamp": "2026-09-20T10:10:00.000Z",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"instanceId": "inst_abc123"
}
}
{
"success": true,
"data": {
"success": true,
"alreadyInState": true,
"connected": true,
"marketId": "clx_secmarket_001"
}
}
{
"success": false,
"data": null,
"error": {
"code": "CHAIN_READ_FAILED",
"message": "The bot or the market could not be read just now, so no step is offered. Retry in a moment."
}
}
