Recipe: End-to-end buyer flow
import { CoreSDK } from "@bosonprotocol/core-sdk"
import { EthersAdapter } from "@bosonprotocol/ethers-sdk"
import { ethers } from "ethers"
const CONFIG_ID = "staging-84532-0" as const
const ENV_NAME = "staging" as const
async function main() {
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL)
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider)
const sdk = CoreSDK.fromDefaultConfig({
web3Lib: new EthersAdapter(provider, wallet),
envName: ENV_NAME,
configId: CONFIG_ID,
})
// 1. Find an offer
const offers = await sdk.getOffers({
where: { voided: false, exchangeToken: USDC_ADDRESS },
orderBy: "price",
orderDirection: "asc",
first: 10,
})
const pick = offers[0]
const tokenAddr = pick.exchangeToken.address ?? pick.exchangeToken
console.log("buying offer", pick.id, "for", pick.price, tokenAddr)
// 2. Approve the ERC-20 (first arg is the TOKEN address, not the offer id)
await (await sdk.approveExchangeToken(tokenAddr, pick.price)).wait()
// 3. Commit — commitToOffer(offerId, overrides?); buyer is the signer.
const commitTx = await sdk.commitToOffer(pick.id)
const receipt = await commitTx.wait()
await sdk.waitForGraphNodeIndexing(receipt.blockNumber)
const exchangeId = sdk.getCommittedExchangeIdFromLogs(receipt.logs)
console.log("committed. exchangeId =", exchangeId)
// 4. Wait for delivery (off-chain, your system)
await waitForDelivery(exchangeId)
// 5. Redeem
await (await sdk.redeemVoucher(exchangeId)).wait()
console.log("redeemed.")
}Common variations
- Native-token offers — skip step 2; pass
{ value: pick.price }on step 3. - Atomic commit-and-redeem — see Buyers → Atomic commit-and-redeem; the SDK currently exposes two-step commit+redeem, with a single-tx variant available via the Diamond's
OrchestrationHandlerFacet. - Gas-less commit — see Recipe → Gas-less commit.
- Token-gated — same flow; the commit reverts if you don't hold the gating token.