oc-opensea-js
Version:
JavaScript SDK for the OpenSea marketplace. Let users buy or sell crypto collectibles and other cryptogoods, all on your own site!
817 lines • 192 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenSeaSDK = void 0;
var bignumber_js_1 = require("bignumber.js");
var ethereumjs_util_1 = require("ethereumjs-util");
var ethers_1 = require("ethers");
var fbemitter_1 = require("fbemitter");
var oc_seaport_js_1 = require("oc-seaport-js");
var constants_1 = require("oc-seaport-js/lib/constants");
var web3_1 = __importDefault(require("web3"));
var wyvern_js_1 = require("wyvern-js");
var WyvernSchemas = __importStar(require("wyvern-schemas"));
var api_1 = require("./api");
var constants_2 = require("./constants");
var contracts_1 = require("./contracts");
var debugging_1 = require("./debugging");
var privateListings_1 = require("./orders/privateListings");
var types_1 = require("./types");
var schema_1 = require("./utils/schema");
var utils_1 = require("./utils/utils");
var OpenSeaSDK = /** @class */ (function () {
/**
* Your very own seaport.
* Create a new instance of OpenSeaJS.
* @param provider Web3 Provider to use for transactions. For example:
* `const provider = new Web3.providers.HttpProvider('https://mainnet.infura.io')`
* @param apiConfig configuration options, including `networkName`
* @param logger logger, optional, a function that will be called with debugging
* information
*/
function OpenSeaSDK(provider, apiConfig, logger) {
if (apiConfig === void 0) { apiConfig = {}; }
var _a;
// Extra gwei to add to the mean gas price when making transactions
this.gasPriceAddition = new bignumber_js_1.BigNumber(3);
// Multiply gas estimate by this factor when making transactions
this.gasIncreaseFactor = constants_2.DEFAULT_GAS_INCREASE_FACTOR;
this.getAmountWithBasisPointsApplied = function (amount, basisPoints) {
return amount
.multipliedBy(basisPoints)
.dividedBy(constants_2.INVERSE_BASIS_POINT)
.toString();
};
// API config
apiConfig.networkName = apiConfig.networkName || types_1.Network.Main;
this.api = new api_1.OpenSeaAPI(apiConfig);
this._wyvernConfigOverride = apiConfig.wyvernConfig;
this._networkName = apiConfig.networkName;
var readonlyProvider = new web3_1.default.providers.HttpProvider("".concat(this.api.apiBaseUrl, "/").concat(constants_2.RPC_URL_PATH));
var useReadOnlyProvider = (_a = apiConfig.useReadOnlyProvider) !== null && _a !== void 0 ? _a : true;
// Web3 Config
this.web3 = new web3_1.default(provider);
this.web3ReadOnly = useReadOnlyProvider
? new web3_1.default(readonlyProvider)
: this.web3;
// Ethers Config
this.ethersProvider = new ethers_1.providers.Web3Provider(provider);
this.seaport = new oc_seaport_js_1.Seaport(this.ethersProvider, {
conduitKeyToConduit: constants_2.CONDUIT_KEYS_TO_CONDUIT,
overrides: {
defaultConduitKey: constants_2.CROSS_CHAIN_DEFAULT_CONDUIT_KEY,
},
});
var networkForWyvernConfig = this._networkName;
if (this._networkName == types_1.Network.Goerli) {
networkForWyvernConfig = types_1.Network.Rinkeby;
}
// WyvernJS config
this._wyvernProtocol = new wyvern_js_1.WyvernProtocol(provider, __assign({ network: networkForWyvernConfig }, apiConfig.wyvernConfig));
// WyvernJS config for readonly (optimization for infura calls)
this._wyvernProtocolReadOnly = useReadOnlyProvider
? new wyvern_js_1.WyvernProtocol(readonlyProvider, __assign({ network: networkForWyvernConfig }, apiConfig.wyvernConfig))
: this._wyvernProtocol;
// WrappedNFTLiquidationProxy Config
this._wrappedNFTFactoryAddress =
this._networkName == types_1.Network.Main
? constants_2.WRAPPED_NFT_FACTORY_ADDRESS_MAINNET
: constants_2.WRAPPED_NFT_FACTORY_ADDRESS_RINKEBY;
this._wrappedNFTLiquidationProxyAddress =
this._networkName == types_1.Network.Main
? constants_2.WRAPPED_NFT_LIQUIDATION_PROXY_ADDRESS_MAINNET
: constants_2.WRAPPED_NFT_LIQUIDATION_PROXY_ADDRESS_RINKEBY;
this._uniswapFactoryAddress =
this._networkName == types_1.Network.Main
? constants_2.UNISWAP_FACTORY_ADDRESS_MAINNET
: constants_2.UNISWAP_FACTORY_ADDRESS_RINKEBY;
// Emit events
this._emitter = new fbemitter_1.EventEmitter();
// Debugging: default to nothing
this.logger = logger || (function (arg) { return arg; });
}
/**
* Add a listener to a marketplace event
* @param event An event to listen for
* @param listener A callback that will accept an object with event data
* @param once Whether the listener should only be called once
*/
OpenSeaSDK.prototype.addListener = function (event, listener, once) {
if (once === void 0) { once = false; }
var subscription = once
? this._emitter.once(event, listener)
: this._emitter.addListener(event, listener);
return subscription;
};
/**
* Remove an event listener, included here for completeness.
* Simply calls `.remove()` on a subscription
* @param subscription The event subscription returned from `addListener`
*/
OpenSeaSDK.prototype.removeListener = function (subscription) {
subscription.remove();
};
/**
* Remove all event listeners. Good idea to call this when you're unmounting
* a component that listens to events to make UI updates
* @param event Optional EventType to remove listeners for
*/
OpenSeaSDK.prototype.removeAllListeners = function (event) {
this._emitter.removeAllListeners(event);
};
/**
* Wraps an arbitrary group of NFTs into their corresponding WrappedNFT ERC20 tokens.
* Emits the `WrapAssets` event when the transaction is prompted.
* @param param0 __namedParameters Object
* @param assets An array of objects with the tokenId and tokenAddress of each of the assets to bundle together.
* @param accountAddress Address of the user's wallet
*/
OpenSeaSDK.prototype.wrapAssets = function (_a) {
var assets = _a.assets, accountAddress = _a.accountAddress;
return __awaiter(this, void 0, void 0, function () {
var schema, wyAssets, tokenIds, tokenAddresses, isMixedBatchOfAssets, txHash;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
schema = this._getSchema(types_1.WyvernSchemaName.ERC721);
wyAssets = assets.map(function (a) { return (0, utils_1.getWyvernAsset)(schema, a); });
tokenIds = wyAssets.map(function (a) { return a.id; });
tokenAddresses = wyAssets.map(function (a) { return a.address; });
isMixedBatchOfAssets = !tokenAddresses.every(function (val, _i, arr) { return val === arr[0]; });
this._dispatch(types_1.EventType.WrapAssets, { assets: wyAssets, accountAddress: accountAddress });
return [4 /*yield*/, (0, utils_1.sendRawTransaction)(this.web3, {
from: accountAddress,
to: this._wrappedNFTLiquidationProxyAddress,
value: 0,
data: (0, schema_1.encodeCall)((0, contracts_1.getMethod)(contracts_1.WrappedNFTLiquidationProxy, "wrapNFTs"), [
tokenIds,
tokenAddresses,
isMixedBatchOfAssets,
]),
}, function (error) {
_this._dispatch(types_1.EventType.TransactionDenied, { error: error, accountAddress: accountAddress });
})];
case 1:
txHash = _b.sent();
return [4 /*yield*/, this._confirmTransaction(txHash, types_1.EventType.WrapAssets, "Wrapping Assets")];
case 2:
_b.sent();
return [2 /*return*/];
}
});
});
};
/**
* Unwraps an arbitrary group of NFTs from their corresponding WrappedNFT ERC20 tokens back into ERC721 tokens.
* Emits the `UnwrapAssets` event when the transaction is prompted.
* @param param0 __namedParameters Object
* @param assets An array of objects with the tokenId and tokenAddress of each of the assets to bundle together.
* @param destinationAddresses Addresses that each resulting ERC721 token will be sent to. Must be the same length as `tokenIds`. Each address corresponds with its respective token ID in the `tokenIds` array.
* @param accountAddress Address of the user's wallet
*/
OpenSeaSDK.prototype.unwrapAssets = function (_a) {
var assets = _a.assets, destinationAddresses = _a.destinationAddresses, accountAddress = _a.accountAddress;
return __awaiter(this, void 0, void 0, function () {
var schema, wyAssets, tokenIds, tokenAddresses, isMixedBatchOfAssets, txHash;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!assets ||
!destinationAddresses ||
assets.length != destinationAddresses.length) {
throw new Error("The 'assets' and 'destinationAddresses' arrays must exist and have the same length.");
}
schema = this._getSchema(types_1.WyvernSchemaName.ERC721);
wyAssets = assets.map(function (a) { return (0, utils_1.getWyvernAsset)(schema, a); });
tokenIds = wyAssets.map(function (a) { return a.id; });
tokenAddresses = wyAssets.map(function (a) { return a.address; });
isMixedBatchOfAssets = !tokenAddresses.every(function (val, _i, arr) { return val === arr[0]; });
this._dispatch(types_1.EventType.UnwrapAssets, {
assets: wyAssets,
accountAddress: accountAddress,
});
return [4 /*yield*/, (0, utils_1.sendRawTransaction)(this.web3, {
from: accountAddress,
to: this._wrappedNFTLiquidationProxyAddress,
value: 0,
data: (0, schema_1.encodeCall)((0, contracts_1.getMethod)(contracts_1.WrappedNFTLiquidationProxy, "unwrapNFTs"), [
tokenIds,
tokenAddresses,
destinationAddresses,
isMixedBatchOfAssets,
]),
}, function (error) {
_this._dispatch(types_1.EventType.TransactionDenied, { error: error, accountAddress: accountAddress });
})];
case 1:
txHash = _b.sent();
return [4 /*yield*/, this._confirmTransaction(txHash, types_1.EventType.UnwrapAssets, "Unwrapping Assets")];
case 2:
_b.sent();
return [2 /*return*/];
}
});
});
};
/**
* Liquidates an arbitrary group of NFTs by atomically wrapping them into their
* corresponding WrappedNFT ERC20 tokens, and then immediately selling those
* ERC20 tokens on their corresponding Uniswap exchange.
* Emits the `LiquidateAssets` event when the transaction is prompted.
* @param param0 __namedParameters Object
* @param assets An array of objects with the tokenId and tokenAddress of each of the assets to bundle together.
* @param accountAddress Address of the user's wallet
* @param uniswapSlippageAllowedInBasisPoints The amount of slippage that a user will tolerate in their Uniswap trade; if Uniswap cannot fulfill the order without more slippage, the whole function will revert.
*/
OpenSeaSDK.prototype.liquidateAssets = function (_a) {
var assets = _a.assets, accountAddress = _a.accountAddress, uniswapSlippageAllowedInBasisPoints = _a.uniswapSlippageAllowedInBasisPoints;
return __awaiter(this, void 0, void 0, function () {
var uniswapSlippage, schema, wyAssets, tokenIds, tokenAddresses, isMixedBatchOfAssets, txHash;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
uniswapSlippage = uniswapSlippageAllowedInBasisPoints === 0
? constants_2.DEFAULT_WRAPPED_NFT_LIQUIDATION_UNISWAP_SLIPPAGE_IN_BASIS_POINTS
: uniswapSlippageAllowedInBasisPoints;
schema = this._getSchema(types_1.WyvernSchemaName.ERC721);
wyAssets = assets.map(function (a) { return (0, utils_1.getWyvernAsset)(schema, a); });
tokenIds = wyAssets.map(function (a) { return a.id; });
tokenAddresses = wyAssets.map(function (a) { return a.address; });
isMixedBatchOfAssets = !tokenAddresses.every(function (val, _i, arr) { return val === arr[0]; });
this._dispatch(types_1.EventType.LiquidateAssets, {
assets: wyAssets,
accountAddress: accountAddress,
});
return [4 /*yield*/, (0, utils_1.sendRawTransaction)(this.web3, {
from: accountAddress,
to: this._wrappedNFTLiquidationProxyAddress,
value: 0,
data: (0, schema_1.encodeCall)((0, contracts_1.getMethod)(contracts_1.WrappedNFTLiquidationProxy, "liquidateNFTs"), [tokenIds, tokenAddresses, isMixedBatchOfAssets, uniswapSlippage]),
}, function (error) {
_this._dispatch(types_1.EventType.TransactionDenied, { error: error, accountAddress: accountAddress });
})];
case 1:
txHash = _b.sent();
return [4 /*yield*/, this._confirmTransaction(txHash, types_1.EventType.LiquidateAssets, "Liquidating Assets")];
case 2:
_b.sent();
return [2 /*return*/];
}
});
});
};
/**
* Purchases a bundle of WrappedNFT tokens from Uniswap and then unwraps them into ERC721 tokens.
* Emits the `PurchaseAssets` event when the transaction is prompted.
* @param param0 __namedParameters Object
* @param numTokensToBuy The number of WrappedNFT tokens to purchase and unwrap
* @param amount The estimated cost in wei for tokens (probably some ratio above the minimum amount to avoid the transaction failing due to frontrunning, minimum amount is found by calling UniswapExchange(uniswapAddress).getEthToTokenOutputPrice(numTokensToBuy.mul(10**18));
* @param contractAddress Address of the corresponding NFT core contract for these NFTs.
* @param accountAddress Address of the user's wallet
*/
OpenSeaSDK.prototype.purchaseAssets = function (_a) {
var numTokensToBuy = _a.numTokensToBuy, amount = _a.amount, contractAddress = _a.contractAddress, accountAddress = _a.accountAddress;
return __awaiter(this, void 0, void 0, function () {
var txHash;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
this._dispatch(types_1.EventType.PurchaseAssets, {
amount: amount,
contractAddress: contractAddress,
accountAddress: accountAddress,
});
return [4 /*yield*/, (0, utils_1.sendRawTransaction)(this.web3, {
from: accountAddress,
to: this._wrappedNFTLiquidationProxyAddress,
value: amount,
data: (0, schema_1.encodeCall)((0, contracts_1.getMethod)(contracts_1.WrappedNFTLiquidationProxy, "purchaseNFTs"), [numTokensToBuy, contractAddress]),
}, function (error) {
_this._dispatch(types_1.EventType.TransactionDenied, { error: error, accountAddress: accountAddress });
})];
case 1:
txHash = _b.sent();
return [4 /*yield*/, this._confirmTransaction(txHash, types_1.EventType.PurchaseAssets, "Purchasing Assets")];
case 2:
_b.sent();
return [2 /*return*/];
}
});
});
};
/**
* Gets the estimated cost or payout of either buying or selling NFTs to Uniswap using either purchaseAssts() or liquidateAssets()
* @param param0 __namedParameters Object
* @param numTokens The number of WrappedNFT tokens to either purchase or sell
* @param isBuying A bool for whether the user is buying or selling
* @param contractAddress Address of the corresponding NFT core contract for these NFTs.
*/
OpenSeaSDK.prototype.getQuoteFromUniswap = function (_a) {
var numTokens = _a.numTokens, isBuying = _a.isBuying, contractAddress = _a.contractAddress;
return __awaiter(this, void 0, void 0, function () {
var wrappedNFTFactory, wrappedNFTAddress, wrappedNFT, uniswapFactory, uniswapExchangeAddress, uniswapExchange, amount, _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
wrappedNFTFactory = new this.web3.eth.Contract(contracts_1.WrappedNFTFactory, this._wrappedNFTFactoryAddress);
return [4 /*yield*/, wrappedNFTFactory.methods
.nftContractToWrapperContract(contractAddress)
.call()];
case 1:
wrappedNFTAddress = _d.sent();
wrappedNFT = new this.web3.eth.Contract(contracts_1.WrappedNFT, wrappedNFTAddress);
uniswapFactory = new this.web3.eth.Contract(contracts_1.UniswapFactory, this._uniswapFactoryAddress);
return [4 /*yield*/, uniswapFactory.methods
.getExchange(wrappedNFTAddress)
.call()];
case 2:
uniswapExchangeAddress = _d.sent();
uniswapExchange = new this.web3.eth.Contract(contracts_1.UniswapExchange, uniswapExchangeAddress);
amount = wyvern_js_1.WyvernProtocol.toBaseUnitAmount((0, utils_1.makeBigNumber)(numTokens), Number(wrappedNFT.methods.decimals().call()));
if (!isBuying) return [3 /*break*/, 4];
_b = parseInt;
return [4 /*yield*/, uniswapExchange.methods
.getEthToTokenOutputPrice(amount.toString())
.call()];
case 3: return [2 /*return*/, _b.apply(void 0, [_d.sent()])];
case 4:
_c = parseInt;
return [4 /*yield*/, uniswapExchange.methods
.getTokenToEthInputPrice(amount.toString())
.call()];
case 5: return [2 /*return*/, _c.apply(void 0, [_d.sent()])];
}
});
});
};
/**
* Wrap ETH into W-ETH.
* W-ETH is needed for placing buy orders (making offers).
* Emits the `WrapEth` event when the transaction is prompted.
* @param param0 __namedParameters Object
* @param amountInEth How much ether to wrap
* @param accountAddress Address of the user's wallet containing the ether
*/
OpenSeaSDK.prototype.wrapEth = function (_a) {
var amountInEth = _a.amountInEth, accountAddress = _a.accountAddress;
return __awaiter(this, void 0, void 0, function () {
var token, amount, txHash;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
token = WyvernSchemas.tokens[this._networkName].canonicalWrappedEther;
amount = wyvern_js_1.WyvernProtocol.toBaseUnitAmount((0, utils_1.makeBigNumber)(amountInEth), token.decimals);
this._dispatch(types_1.EventType.WrapEth, { accountAddress: accountAddress, amount: amount });
return [4 /*yield*/, (0, utils_1.sendRawTransaction)(this.web3, {
from: accountAddress,
to: token.address,
value: amount,
data: (0, schema_1.encodeCall)((0, contracts_1.getMethod)(contracts_1.CanonicalWETH, "deposit"), []),
}, function (error) {
_this._dispatch(types_1.EventType.TransactionDenied, { error: error, accountAddress: accountAddress });
})];
case 1:
txHash = _b.sent();
return [4 /*yield*/, this._confirmTransaction(txHash, types_1.EventType.WrapEth, "Wrapping ETH")];
case 2:
_b.sent();
return [2 /*return*/];
}
});
});
};
/**
* Unwrap W-ETH into ETH.
* Emits the `UnwrapWeth` event when the transaction is prompted.
* @param param0 __namedParameters Object
* @param amountInEth How much W-ETH to unwrap
* @param accountAddress Address of the user's wallet containing the W-ETH
*/
OpenSeaSDK.prototype.unwrapWeth = function (_a) {
var amountInEth = _a.amountInEth, accountAddress = _a.accountAddress;
return __awaiter(this, void 0, void 0, function () {
var token, amount, txHash;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
token = WyvernSchemas.tokens[this._networkName].canonicalWrappedEther;
amount = wyvern_js_1.WyvernProtocol.toBaseUnitAmount((0, utils_1.makeBigNumber)(amountInEth), token.decimals);
this._dispatch(types_1.EventType.UnwrapWeth, { accountAddress: accountAddress, amount: amount });
return [4 /*yield*/, (0, utils_1.sendRawTransaction)(this.web3, {
from: accountAddress,
to: token.address,
value: 0,
data: (0, schema_1.encodeCall)((0, contracts_1.getMethod)(contracts_1.CanonicalWETH, "withdraw"), [
amount.toString(),
]),
}, function (error) {
_this._dispatch(types_1.EventType.TransactionDenied, { error: error, accountAddress: accountAddress });
})];
case 1:
txHash = _b.sent();
return [4 /*yield*/, this._confirmTransaction(txHash, types_1.EventType.UnwrapWeth, "Unwrapping W-ETH")];
case 2:
_b.sent();
return [2 /*return*/];
}
});
});
};
OpenSeaSDK.prototype.getFees = function (_a) {
var _b;
var asset = _a.openseaAsset, paymentTokenAddress = _a.paymentTokenAddress, startAmount = _a.startAmount, endAmount = _a.endAmount;
return __awaiter(this, void 0, void 0, function () {
var openseaSellerFeeBasisPoints, collectionSellerFeeBasisPoints, sellerBasisPoints, getConsiderationItem, getConsiderationItemsFromSellerFees;
var _this = this;
return __generator(this, function (_c) {
openseaSellerFeeBasisPoints = constants_2.DEFAULT_SELLER_FEE_BASIS_POINTS;
collectionSellerFeeBasisPoints = (0, utils_1.feesToBasisPoints)((_b = asset.collection.fees) === null || _b === void 0 ? void 0 : _b.sellerFees);
sellerBasisPoints = constants_2.INVERSE_BASIS_POINT -
openseaSellerFeeBasisPoints -
collectionSellerFeeBasisPoints;
getConsiderationItem = function (basisPoints, recipient) {
return {
token: paymentTokenAddress,
amount: _this.getAmountWithBasisPointsApplied(startAmount, basisPoints),
endAmount: _this.getAmountWithBasisPointsApplied(endAmount !== null && endAmount !== void 0 ? endAmount : startAmount, basisPoints),
recipient: recipient,
};
};
getConsiderationItemsFromSellerFees = function (fees) {
var sellerFees = fees.sellerFees;
return Array.from(sellerFees.entries()).map(function (_a) {
var recipient = _a[0], basisPoints = _a[1];
return getConsiderationItem(basisPoints, recipient);
});
};
return [2 /*return*/, {
sellerFee: getConsiderationItem(sellerBasisPoints),
openseaSellerFee: getConsiderationItem(openseaSellerFeeBasisPoints, constants_2.OPENSEA_FEE_RECIPIENT),
collectionSellerFees: collectionSellerFeeBasisPoints > 0 && asset.collection.fees
? getConsiderationItemsFromSellerFees(asset.collection.fees)
: [],
}];
});
});
};
OpenSeaSDK.prototype.getAssetItems = function (assets, quantities, fallbackSchema) {
var _this = this;
if (quantities === void 0) { quantities = []; }
return assets.map(function (asset, index) {
var _a, _b, _c;
return ({
itemType: (0, utils_1.getAssetItemType)((_a = _this._getSchemaName(asset)) !== null && _a !== void 0 ? _a : fallbackSchema),
token: (0, utils_1.getAddressAfterRemappingSharedStorefrontAddressToLazyMintAdapterAddress)(asset.tokenAddress),
identifier: (_b = asset.tokenId) !== null && _b !== void 0 ? _b : undefined,
amount: (_c = quantities[index].toString()) !== null && _c !== void 0 ? _c : "1",
});
});
};
/**
* Create a buy order to make an offer on an asset.
* @param options Options for creating the buy order
* @param options.asset The asset to trade
* @param options.accountAddress Address of the maker's wallet
* @param options.startAmount Value of the offer, in units of the payment token (or wrapped ETH if no payment token address specified)
* @param options.quantity The number of assets to bid for (if fungible or semi-fungible). Defaults to 1. In units, not base units, e.g. not wei
* @param options.domain An optional domain to be hashed and included in the first four bytes of the random salt.
* @param options.salt Arbitrary salt. If not passed in, a random salt will be generated with the first four bytes being the domain hash or empty.
* @param options.expirationTime Expiration time for the order, in seconds
* @param options.paymentTokenAddress Optional address for using an ERC-20 token in the order. If unspecified, defaults to WETH
*/
OpenSeaSDK.prototype.createBuyOrder = function (_a) {
var _b;
var asset = _a.asset, accountAddress = _a.accountAddress, startAmount = _a.startAmount, _c = _a.quantity, quantity = _c === void 0 ? 1 : _c, _d = _a.domain, domain = _d === void 0 ? "" : _d, _e = _a.salt, salt = _e === void 0 ? "" : _e, expirationTime = _a.expirationTime, paymentTokenAddress = _a.paymentTokenAddress;
return __awaiter(this, void 0, void 0, function () {
var openseaAsset, considerationAssetItems, basePrice, _f, openseaSellerFee, collectionSellerFees, considerationFeeItems, executeAllActions, order;
return __generator(this, function (_g) {
switch (_g.label) {
case 0:
if (!asset.tokenId) {
throw new Error("Asset must have a tokenId");
}
paymentTokenAddress =
paymentTokenAddress !== null && paymentTokenAddress !== void 0 ? paymentTokenAddress : constants_2.WETH_ADDRESS_BY_NETWORK[this._networkName];
return [4 /*yield*/, this.api.getAsset(asset)];
case 1:
openseaAsset = _g.sent();
considerationAssetItems = this.getAssetItems([openseaAsset], [(0, utils_1.makeBigNumber)(quantity)]);
return [4 /*yield*/, this._getPriceParameters(types_1.OrderSide.Buy, paymentTokenAddress, (0, utils_1.makeBigNumber)(expirationTime !== null && expirationTime !== void 0 ? expirationTime : (0, utils_1.getMaxOrderExpirationTimestamp)()), (0, utils_1.makeBigNumber)(startAmount))];
case 2:
basePrice = (_g.sent()).basePrice;
return [4 /*yield*/, this.getFees({
openseaAsset: openseaAsset,
paymentTokenAddress: paymentTokenAddress,
startAmount: basePrice,
})];
case 3:
_f = _g.sent(), openseaSellerFee = _f.openseaSellerFee, collectionSellerFees = _f.collectionSellerFees;
considerationFeeItems = __spreadArray([openseaSellerFee], collectionSellerFees, true);
return [4 /*yield*/, this.seaport.createOrder({
offer: [
{
token: paymentTokenAddress,
amount: basePrice.toString(),
},
],
consideration: __spreadArray(__spreadArray([], considerationAssetItems, true), considerationFeeItems, true),
endTime: (_b = expirationTime === null || expirationTime === void 0 ? void 0 : expirationTime.toString()) !== null && _b !== void 0 ? _b : (0, utils_1.getMaxOrderExpirationTimestamp)().toString(),
zone: constants_2.DEFAULT_ZONE_BY_NETWORK[this._networkName],
domain: domain,
salt: salt,
restrictedByZone: true,
allowPartialFills: true,
}, accountAddress)];
case 4:
executeAllActions = (_g.sent()).executeAllActions;
return [4 /*yield*/, executeAllActions()];
case 5:
order = _g.sent();
return [2 /*return*/, this.api.postOrder(order, { protocol: "seaport", side: "bid" })];
}
});
});
};
/**
* Create a sell order to auction an asset.
* @param options Options for creating the sell order
* @param options.asset The asset to trade
* @param options.accountAddress Address of the maker's wallet
* @param options.startAmount Price of the asset at the start of the auction. Units are in the amount of a token above the token's decimal places (integer part). For example, for ether, expected units are in ETH, not wei.
* @param options.endAmount Optional price of the asset at the end of its expiration time. Units are in the amount of a token above the token's decimal places (integer part). For example, for ether, expected units are in ETH, not wei.
* @param options.quantity The number of assets to sell (if fungible or semi-fungible). Defaults to 1. In units, not base units, e.g. not wei.
* @param options.domain An optional domain to be hashed and included in the first four bytes of the random salt.
* @param options.salt Arbitrary salt. If not passed in, a random salt will be generated with the first four bytes being the domain hash or empty.
* @param options.listingTime Optional time when the order will become fulfillable, in UTC seconds. Undefined means it will start now.
* @param options.expirationTime Expiration time for the order, in UTC seconds.
* @param options.paymentTokenAddress Address of the ERC-20 token to accept in return. If undefined or null, uses Ether.
* @param options.buyerAddress Optional address that's allowed to purchase this item. If specified, no other address will be able to take the order, unless its value is the null address.
*/
OpenSeaSDK.prototype.createSellOrder = function (_a) {
var _b;
var asset = _a.asset, accountAddress = _a.accountAddress, startAmount = _a.startAmount, endAmount = _a.endAmount, _c = _a.quantity, quantity = _c === void 0 ? 1 : _c, _d = _a.domain, domain = _d === void 0 ? "" : _d, _e = _a.salt, salt = _e === void 0 ? "" : _e, listingTime = _a.listingTime, expirationTime = _a.expirationTime, _f = _a.paymentTokenAddress, paymentTokenAddress = _f === void 0 ? constants_2.NULL_ADDRESS : _f, buyerAddress = _a.buyerAddress;
return __awaiter(this, void 0, void 0, function () {
var openseaAsset, offerAssetItems, _g, basePrice, endPrice, _h, sellerFee, openseaSellerFee, collectionSellerFees, considerationFeeItems, executeAllActions, order;
return __generator(this, function (_j) {
switch (_j.label) {
case 0:
if (!asset.tokenId) {
throw new Error("Asset must have a tokenId");
}
return [4 /*yield*/, this.api.getAsset(asset)];
case 1:
openseaAsset = _j.sent();
offerAssetItems = this.getAssetItems([openseaAsset], [(0, utils_1.makeBigNumber)(quantity)]);
return [4 /*yield*/, this._getPriceParameters(types_1.OrderSide.Sell, paymentTokenAddress, (0, utils_1.makeBigNumber)(expirationTime !== null && expirationTime !== void 0 ? expirationTime : (0, utils_1.getMaxOrderExpirationTimestamp)()), (0, utils_1.makeBigNumber)(startAmount), endAmount !== undefined ? (0, utils_1.makeBigNumber)(endAmount) : undefined)];
case 2:
_g = _j.sent(), basePrice = _g.basePrice, endPrice = _g.endPrice;
return [4 /*yield*/, this.getFees({
openseaAsset: openseaAsset,
paymentTokenAddress: paymentTokenAddress,
startAmount: basePrice,
endAmount: endPrice,
})];
case 3:
_h = _j.sent(), sellerFee = _h.sellerFee, openseaSellerFee = _h.openseaSellerFee, collectionSellerFees = _h.collectionSellerFees;
considerationFeeItems = [
sellerFee,
openseaSellerFee,
collectionSellerFees,
].filter(function (item) { return item !== undefined; });
if (buyerAddress) {
considerationFeeItems.push.apply(considerationFeeItems, (0, privateListings_1.getPrivateListingConsiderations)(offerAssetItems, buyerAddress));
}
return [4 /*yield*/, this.seaport.createOrder({
offer: offerAssetItems,
consideration: considerationFeeItems,
startTime: listingTime,
endTime: (_b = expirationTime === null || expirationTime === void 0 ? void 0 : expirationTime.toString()) !== null && _b !== void 0 ? _b : (0, utils_1.getMaxOrderExpirationTimestamp)().toString(),
zone: constants_2.DEFAULT_ZONE_BY_NETWORK[this._networkName],
domain: domain,
salt: salt,
restrictedByZone: true,
allowPartialFills: true,
}, accountAddress)];
case 4:
executeAllActions = (_j.sent()).executeAllActions;
return [4 /*yield*/, executeAllActions()];
case 5:
order = _j.sent();
return [2 /*return*/, this.api.postOrder(order, { protocol: "seaport", side: "ask" })];
}
});
});
};
OpenSeaSDK.prototype.fulfillPrivateOrder = function (_a) {
var _b;
var order = _a.order, accountAddress = _a.accountAddress;
return __awaiter(this, void 0, void 0, function () {
var transactionHash, _c, counterOrder, fulfillments, transaction, transactionReceipt;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
_c = order.protocolAddress;
switch (_c) {
case constants_1.CROSS_CHAIN_SEAPORT_ADDRESS: return [3 /*break*/, 1];
}
return [3 /*break*/, 4];
case 1:
if (!((_b = order.taker) === null || _b === void 0 ? void 0 : _b.address)) {
throw new Error("Order is not a private listing must have a taker address");
}
counterOrder = (0, privateListings_1.constructPrivateListingCounterOrder)(order.protocolData, order.taker.address);
fulfillments = (0, privateListings_1.getPrivateListingFulfillments)(order.protocolData);
return [4 /*yield*/, this.seaport
.matchOrders({
orders: [order.protocolData, counterOrder],
fulfillments: fulfillments,
overrides: {
value: counterOrder.parameters.offer[0].startAmount,
},
accountAddress: accountAddress,
})
.transact()];
case 2:
transaction = _d.sent();
return [4 /*yield*/, transaction.wait()];
case 3:
transactionReceipt = _d.sent();
transactionHash = transactionReceipt.transactionHash;
return [3 /*break*/, 5];
case 4: throw new Error("Unsupported protocol");
case 5: return [4 /*yield*/, this._confirmTransaction(transactionHash, types_1.EventType.MatchOrders, "Fulfilling order")];
case 6:
_d.sent();
return [2 /*return*/, transactionHash];
}
});
});
};
/**
* Fullfill or "take" an order for an asset, either a buy or sell order
* @param options fullfillment options
* @param options.order The order to fulfill, a.k.a. "take"
* @param options.accountAddress The taker's wallet address
* @param options.recipientAddress The optional address to receive the order's item(s) or curriencies. If not specified, defaults to accountAddress
* @returns Transaction hash for fulfilling the order
*/
OpenSeaSDK.prototype.fulfillOrder = function (_a) {
var order = _a.order, accountAddress = _a.accountAddress, recipientAddress = _a.recipientAddress, payableOverridesOptions = _a.payableOverridesOptions;
return __awaiter(this, void 0, void 0, function () {
var isPrivateListing, transactionHash, _b, executeAllActions, transaction;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
isPrivateListing = !!order.taker;
if (isPrivateListing) {
if (recipientAddress) {
throw new Error("Private listings cannot be fulfilled with a recipient address");
}
return [2 /*return*/, this.fulfillPrivateOrder({
order: order,
accountAddress: accountAddress,
})];
}
_b = order.protocolAddress;
switch (_b) {
case constants_1.CROSS_CHAIN_SEAPORT_ADDRESS: return [3 /*break*/, 1];
}
return [3 /*break*/, 4];
case 1: return [4 /*yield*/, this.seaport.fulfillOrder({
order: order.protocolData,
accountAddress: accountAddress,
recipientAddress: recipientAddress,
payableOverridesOptions: payableOverridesOptions,
})];
case 2:
executeAllActions = (_c.sent()).executeAllActions;
return [4 /*yield*/, executeAllActions()];
case 3:
transaction = _c.sent();
transactionHash = transaction.hash;
return [3 /*break*/, 5];
case 4: throw new Error("Unsupported protocol");
case 5: return [4 /*yield*/, this._confirmTransaction(transactionHash, types_1.EventType.MatchOrders, "Fulfilling order")];
case 6:
_c.sent();
return [2 /*return*/, transactionHash];
}
});
});
};
/**
* Fullfill or "take" an order for an asset, either a buy or sell order
* @param param0 __namedParamaters Object
* @param order The order to fulfill, a.k.a. "take"
* @param accountAddress The taker's wallet address
* @param recipientAddress The optional address to receive the order's item(s) or curriencies. If not specified, defaults to accountAddress.
* @param referrerAddress The optional address that referred the order
* @returns Transaction hash for fulfilling the order
*/
OpenSeaSDK.prototype.fulfillOrderLegacyWyvern = function (_a) {
var order = _a.order, accountAddress = _a.accountAddress, recipientAddress = _a.recipientAddress, referrerAddress = _a.referrerAddress;
return __awaiter(this, void 0, void 0, function () {
var matchingOrder, _b, buy, sell, metadata, transactionHash;
var _this = this;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
matchingOrder = this._makeMatchingOrder({
order: order,
accountAddress: accountAddress,
recipientAddress: recipientAddress || accountAddress,
});
_b = (0, utils_1.assignOrdersToSides)(order, matchingOrder), buy = _b.buy, sell = _b.sell;
metadata = this._getMetadata(order, referrerAddress);
return [4 /*yield*/, this._atomicMatch({
buy: buy,
sell: sell,
accountAddress: accountAddress,
metadata: metadata,
})];
case 1:
transactionHash = _c.sent();
return [4 /*yield*/, this._confirmTransaction(transactionHash, types_1.EventType.MatchOrders, "Fulfilling order", function () { return __awaiter(_this, void 0, void 0,