InviaInvia
App
SDK/Cancel & expire

Cancel & expire

An offer's lifecycle ends in one of three ways: a maker cancels it, anyone expires it after the deadline, or the final fill clears the remaining size. All three are exposed on the program client.

Cancel (maker only)

The maker calls cancel_offer to close the offer early. The program returns escrowed assets to the maker and refunds rent for both vaults and the offer account itself in a single transaction.

import { PublicKey } from "@solana/web3.js";

await invia.program.cancelOffer(wallet, {
  offer: new PublicKey(offerPda),
  tokenMint: new PublicKey(tokenMintAddr),
  paymentMint: new PublicKey(paymentMintAddr),
});

Cancellation is free for makers. There is no fee, no penalty, and no time window.

Expire (permissionless)

Once expires_at has passed, anyone can call expire_offer. The program returns escrowed assets to the maker exactly the same way cancel does, plus pays a small SOL bounty (EXPIRY_BOUNTY_LAMPORTS) to the caller.

await invia.program.expireOffer(wallet, {
  offer: new PublicKey(offerPda),
  maker: new PublicKey(makerAddr),
  tokenMint: new PublicKey(tokenMintAddr),
  paymentMint: new PublicKey(paymentMintAddr),
});
Run a keeper

An idle SDK consumer can scan getOffers({ status: "expired" }) and submit expirations. The bounty covers the lamports cost in nearly all cases, so a small bot pays for itself.

Close (after a full fill)

When take_offer decrements remaining_size to 0, the offer account is not automatically closed; only its vaults end up empty. The maker (or anyone covering the small fee) can call close_offer to release the offer PDA's rent back to the maker:

await invia.program.closeOffer(wallet, {
  offer: new PublicKey(offerPda),
  maker: new PublicKey(makerAddr),
  tokenMint: new PublicKey(tokenMintAddr),
  paymentMint: new PublicKey(paymentMintAddr),
});

close_offer errors if remaining_size != 0. It is safe to call from a keeper.

Building the instructions yourself

The program client also exposes the raw builders if you want to add ixs to a custom transaction:

const { ix } = invia.program.buildCancelOfferIx({
  maker: new PublicKey(wallet.address),
  offer: new PublicKey(offerPda),
  tokenMint: new PublicKey(tokenMintAddr),
  paymentMint: new PublicKey(paymentMintAddr),
});

Same shape for buildExpireOfferIx and buildCloseOfferIx.