opensea-js
Version:
TypeScript SDK for the OpenSea marketplace helps developers build new experiences using NFTs and our marketplace data
231 lines • 12.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CancellationManager = void 0;
const utils_1 = require("../orders/utils");
const types_1 = require("../types");
const utils_2 = require("../utils/utils");
/**
* Order cancellation operations
*/
class CancellationManager {
constructor(context) {
this.context = context;
}
/**
* Cancel an order onchain, preventing it from ever being fulfilled.
* This method accepts either a full OrderV2 object or an order hash with protocol address.
*
* @param options
* @param options.order The order to cancel (OrderV2 object)
* @param options.orderHash Optional order hash to cancel. Must provide protocolAddress if using this.
* @param options.accountAddress The account address that will be cancelling the order.
* @param options.protocolAddress Required when using orderHash. The Seaport protocol address for the order.
* @param options.domain An optional domain to be hashed and included at the end of fulfillment calldata. This can be used for on-chain order attribution to assist with analytics.
*
* @throws Error if neither order nor orderHash is provided.
* @throws Error if the accountAddress is not available through wallet or provider.
* @throws Error if the order's protocol address is not supported by OpenSea. See {@link isValidProtocol}.
*/
async cancelOrder({ order, orderHash, accountAddress, protocolAddress = utils_1.DEFAULT_SEAPORT_CONTRACT_ADDRESS, domain, }) {
// Validate input
if (!order && !orderHash) {
throw new Error("Either order or orderHash must be provided to cancel order");
}
// Check account availability after parameter validation
await this.context.requireAccountIsAvailable(accountAddress);
let orderComponents;
let effectiveProtocolAddress;
if (order) {
// Using OrderV2 object directly
(0, utils_2.requireValidProtocol)(order.protocolAddress);
effectiveProtocolAddress = order.protocolAddress;
orderComponents = order.protocolData.parameters;
this.context.dispatch(types_1.EventType.CancelOrder, {
orderV2: order,
accountAddress,
});
}
else if (orderHash) {
// Fetch order from API using order hash
(0, utils_2.requireValidProtocol)(protocolAddress);
const fetchedOrder = await this.context.api.getOrderByHash(orderHash, protocolAddress, this.context.chain);
(0, utils_2.requireValidProtocol)(fetchedOrder.protocol_address);
effectiveProtocolAddress = fetchedOrder.protocol_address;
orderComponents = fetchedOrder.protocol_data.parameters;
this.context.dispatch(types_1.EventType.CancelOrder, {
order: fetchedOrder,
accountAddress,
});
}
else {
// Should never reach here due to earlier validation
throw new Error("Invalid input");
}
// Transact and get the transaction hash
const transactionHash = await this.cancelSeaportOrders({
orders: [orderComponents],
accountAddress,
domain,
protocolAddress: effectiveProtocolAddress,
});
// Await transaction confirmation
await this.context.confirmTransaction(transactionHash, types_1.EventType.CancelOrder, "Cancelling order");
}
/**
* Cancel multiple orders onchain, preventing them from being fulfilled.
* This method accepts either full OrderV2 objects, OrderComponents, or order hashes with protocol address.
*
* **Event Behavior**: For backwards compatibility with the singular `cancelOrder` method,
* this method dispatches a `CancelOrder` event for the first order only, and only when
* an OrderV2 object is available (either provided directly or fetched via orderHashes).
* No event is dispatched when using OrderComponents directly, as they lack the full order data.
*
* @param options
* @param options.orders Array of orders to cancel. Can be OrderV2 objects or OrderComponents.
* @param options.orderHashes Optional array of order hashes to cancel. Must provide protocolAddress if using this.
* @param options.accountAddress The account address cancelling the orders.
* @param options.protocolAddress Required when using orderHashes. The Seaport protocol address for the orders.
* @param options.domain An optional domain to be hashed and included at the end of fulfillment calldata.
* @param options.overrides Transaction overrides, ignored if not set.
* @returns Transaction hash of the cancellation.
*
* @throws Error if orderHashes is provided without protocolAddress.
* @throws Error if neither orders nor orderHashes is provided.
* @throws Error if the accountAddress is not available through wallet or provider.
* @throws Error if the order's protocol address is not supported by OpenSea. See {@link isValidProtocol}.
*/
async cancelOrders({ orders, orderHashes, accountAddress, protocolAddress = utils_1.DEFAULT_SEAPORT_CONTRACT_ADDRESS, domain, overrides, }) {
// Validate input before making any external calls
if (!orders && !orderHashes) {
throw new Error("Either orders or orderHashes must be provided to cancel orders");
}
if (orders && orders.length === 0) {
throw new Error("At least one order must be provided");
}
if (orderHashes && orderHashes.length === 0) {
throw new Error("At least one order hash must be provided");
}
(0, utils_2.requireValidProtocol)(protocolAddress);
// Check account availability after parameter validation
await this.context.requireAccountIsAvailable(accountAddress);
let orderComponents;
let effectiveProtocolAddress = protocolAddress;
if (orders) {
// Extract OrderComponents from either OrderV2 objects or use OrderComponents directly
let firstOrderV2;
orderComponents = orders.map((order) => {
if ("protocolData" in order) {
// It's an OrderV2 object
const orderV2 = order;
(0, utils_2.requireValidProtocol)(orderV2.protocolAddress);
effectiveProtocolAddress = orderV2.protocolAddress;
if (!firstOrderV2) {
firstOrderV2 = orderV2;
}
return orderV2.protocolData.parameters;
}
else {
// It's already OrderComponents
return order;
}
});
// Dispatch event for the first OrderV2 if available
if (firstOrderV2) {
this.context.dispatch(types_1.EventType.CancelOrder, {
orderV2: firstOrderV2,
accountAddress,
});
}
}
else if (orderHashes) {
// Fetch orders from the API using order hashes
const fetchedOrders = [];
for (const hash of orderHashes) {
const fetched = await this.context.api.getOrderByHash(hash, protocolAddress, this.context.chain);
fetchedOrders.push(fetched);
}
// Extract OrderComponents from the fetched orders
orderComponents = fetchedOrders.map((fetched) => {
(0, utils_2.requireValidProtocol)(fetched.protocol_address);
effectiveProtocolAddress = fetched.protocol_address;
return fetched.protocol_data.parameters;
});
// Dispatch event for the first fetched order
if (fetchedOrders.length > 0) {
this.context.dispatch(types_1.EventType.CancelOrder, {
order: fetchedOrders[0],
accountAddress,
});
}
}
else {
// Should never reach here due to earlier validation
throw new Error("Invalid input");
}
// Transact and get the transaction hash
const transactionHash = await this.cancelSeaportOrders({
orders: orderComponents,
accountAddress,
domain,
protocolAddress: effectiveProtocolAddress,
overrides,
});
// Await transaction confirmation
await this.context.confirmTransaction(transactionHash, types_1.EventType.CancelOrder, `Cancelling ${orderComponents.length} order(s)`);
return transactionHash;
}
/**
* Cancel orders onchain, preventing them from being fulfilled.
* @param options
* @param options.orders The orders to cancel
* @param options.accountAddress The account address cancelling the orders.
* @param options.domain An optional domain to be hashed and included at the end of fulfillment calldata.
* This can be used for on-chain order attribution to assist with analytics.
* @param options.overrides Transaction overrides, ignored if not set.
* @returns Transaction hash of the order.
*/
async cancelSeaportOrders({ orders, accountAddress, domain, protocolAddress = utils_1.DEFAULT_SEAPORT_CONTRACT_ADDRESS, overrides, }) {
const seaport = (0, utils_2.getSeaportInstance)(protocolAddress, this.context.seaport);
const transaction = await seaport
.cancelOrders(orders, accountAddress, domain, overrides)
.transact();
return transaction.hash;
}
/**
* Get the offerer signature for canceling an order offchain.
* The signature will only be valid if the signer address is the address of the order's offerer.
*/
async getOffererSignature(protocolAddress, orderHash, chain) {
const chainId = (0, utils_2.getChainId)(chain);
const name = "Seaport";
const version = (0, utils_2.getSeaportVersion)(protocolAddress);
if (typeof this.context.signerOrProvider.signTypedData ==
"undefined") {
throw new Error("Please pass an ethers Signer into this sdk to derive an offerer signature");
}
return this.context.signerOrProvider.signTypedData({ chainId, name, version, verifyingContract: protocolAddress }, { OrderHash: [{ name: "orderHash", type: "bytes32" }] }, { orderHash });
}
/**
* Offchain cancel an order, offer or listing, by its order hash when protected by the SignedZone.
* Protocol and Chain are required to prevent hash collisions.
* Please note cancellation is only assured if a fulfillment signature was not vended prior to cancellation.
* @param protocolAddress The Seaport address for the order.
* @param orderHash The order hash, or external identifier, of the order.
* @param chain The chain where the order is located.
* @param offererSignature An EIP-712 signature from the offerer of the order.
* If this is not provided, the API key used to initialize the SDK must belong to the order's offerer.
* The signature must be a EIP-712 signature consisting of the order's Seaport contract's
* name, version, address, and chain. The struct to sign is `OrderHash` containing a
* single bytes32 field.
* @param useSignerToDeriveOffererSignature Derive the offererSignature from the Ethers signer passed into this sdk.
* @returns The response from the API.
*/
async offchainCancelOrder(protocolAddress, orderHash, chain = this.context.chain, offererSignature, useSignerToDeriveOffererSignature) {
if (useSignerToDeriveOffererSignature) {
offererSignature = await this.getOffererSignature(protocolAddress, orderHash, chain);
}
return this.context.api.offchainCancelOrder(protocolAddress, orderHash, chain, offererSignature);
}
}
exports.CancellationManager = CancellationManager;
//# sourceMappingURL=cancellation.js.map