Skip to main content
Not yet released. The lending module described here ships with @trusset/sdk 0.4.0, which is not on npm yet: npm install @trusset/sdk installs 0.1.0, which carries the customers module only. Until 0.4.0 is published, call the Lending API directly.
This page is for the risk or operations engineer who wires a market into their own systems. After reading it you will know how to create each kind of hook, verify the webhook deliveries it sends, test it, and rotate its signing secret. A hook is a rule Trusset stores and evaluates off chain. It never signs or broadcasts a transaction, so nothing on this page takes a signer. No hook result blocks a liquidation: a failing check is recorded and the liquidation goes ahead. A liquidation runs the active beforeLiquidation and afterLiquidation hooks of every instance that holds the market, once per liquidation. Create Hook describes the timing in full.

Receive liquidation notices

An afterLiquidation hook with actionType: 'inform' announces every liquidation of the market to a URL you run.
Store webhookSecret when the hook is created. This response is the only place it appears: later reads carry signed: true and never the secret. If it is lost, issue a new one with rotateSecret. webhookUrl and riskUri must be http or https URLs on a public host. The SDK checks the scheme before sending. The API refuses a private, reserved or local host, and checks the address again on every outbound call. A delivery is queued, then sent and retried by a worker, up to eight attempts in all. A liquidation is announced to a hook at most once, and every attempt of one delivery carries the same id, so a retry is never a second event.

Verify a delivery

Each delivery is a POST. Its x-webhook-signature header is an HMAC-SHA256 in hex, keyed with webhookSecret exactly as returned, over the x-webhook-timestamp value, a dot, and the raw request body.
Compute the signature over the body bytes as they arrived, before any JSON parsing. Each retry carries a fresh timestamp and a fresh signature. De-duplicate on x-trusset-delivery-id, which stays the same across retries. The body carries id, event, hookId, marketId, emittedAt and timestamp. A liquidation adds the loan, the amounts, the borrower, the transaction hash and the outcome. A monitor breach adds the monitor and its failing fields. Signed deliveries lists every field and the retry schedule. A 2xx answer delivers it. A 5xx, 408, 425 or 429 answer, a timeout or a connection failure is retried. Any other answer, a redirect included, fails the delivery for good.

Monitor an external risk source

A monitorRisk hook fetches riskUri on a schedule and checks fields of the JSON it returns. A field with a dot-notation path fails when the path resolves to nothing, or when its comparison with threshold fails.
The SDK requires riskUri and at least one riskFields entry for this type. A hook without checkFrequency is never scheduled and runs only through execute. The scheduler picks a new monitor up at its next wake-up, not at the moment of this call. When a monitor evaluates to false, every active afterLiquidation hook that lists it in triggerHookIds acts on the breach. An inform hook then sends a riskBreach delivery. A buy hook only logs that a breach carries no auction to act on.
hookId here is the monitor’s id. A hook that lists triggers acts only when every listed hook is active and its last counted run returned false.

Check a loan before liquidation

A beforeLiquidation hook evaluates parameterChecks and records the result. It does not block the liquidation.
The checks run against the liquidation’s data, not against chain state. A liquidation’s data carries debtValue and none of the other four parameters, so a check on healthFactor, collateralValue, collateralRatio or interestAccrued fails on every liquidation. Those parameters only take effect in a test run where you supply them.

Test a hook

execute runs one hook now and returns its outcome, whether or not the hook is active. What it needs depends on the type: nothing for monitorRisk, loanData for beforeLiquidation, and liquidationData for afterLiquidation.
The call answers HTTP 200 whenever the hook ran, including when the hook itself failed. Read the outcome from success and result. A monitor run lists each evaluated field in fields, and a check run lists checkResults. Executing an inform hook sends a real delivery to its webhookUrl. The run returns at once with queued: true and the deliveryId, before anything is sent. Pass an eventKey to make the call idempotent: a second call with the same key queues nothing and returns duplicate: true.
The SDK never repeats an execute call after an ambiguous failure, because a repeat without eventKey queues a second delivery.

Buy hooks return steps, not bids

A buy hook never bids. It returns an approval and a bidOnAuction step, priced when they were built, and nothing confirms them. The auction charges its price when the bid lands. The bid reverts if, for example, the auction ended, the price is stale or the signer is the borrower. The balance check before the steps reads only the instance’s registered wallet, whichever wallet signs.
Treat a buy run as a price signal. To place the bid, use auctions.bid with the auction id from the run. It builds the same two steps, signs them with the bidder’s wallet and confirms the mined bid. See Auctions.

Change, pause or delete a hook

update changes only the fields you send. Arrays and webhookPayload are replaced whole, not merged. Validation runs against the merged record, so switching actionType to inform on a hook without a webhookUrl is refused.
A URL, checkFrequency, actionType or riskThreshold cannot be unset once stored. An inactive hook drops out of everything that runs on its own, and execute still runs it when called for it directly. Deliveries it queued before it was paused are still sent.
remove deletes the hook, its execution log and its deliveries, including any not yet sent, which are then never sent. It cannot be undone. Other hooks that list the deleted hook in triggerHookIds never act again until you remove the id from them with update.
To stop a hook and keep its history, use toggle instead.

Rotate the signing secret

The previous secret stops at once, with no overlap. Every attempt sent after this call is signed with the new secret, including retries of deliveries queued earlier. A receiver that rejects the new signature with a 4xx other than 408, 425 or 429 fails that delivery for good.
Switch the receiver to the new secret right away, or have it answer 503 while it switches so the delivery is retried. A hook whose signed reads false holds no secret, and rotating issues it one.

Read hooks, runs and deliveries

list returns every hook on the market, newest first. get refuses a hook of another market with HOOK_NOT_FOUND. executions and deliveries return newest first and page with limit, from 1 to 200, and offset. The execution log and a hook’s executionCount are different counts. An unmet trigger, a skipped bid or a short wallet balance adds a log entry without counting as a run. An inform run is logged when its delivery is delivered or fails for good, not when it is queued. A delivery’s status is PENDING, RETRYING, DELIVERED or FAILED. Delivered and failed deliveries are kept for at least 30 days.

Methods and endpoints