@reservoir0x/reservoir-kit-client
Version:
ReservoirKit is the official frontend kit to get you started building dApps with the ReservoirProtocol.
573 lines (510 loc) • 27.1 kB
JavaScript
var $jXfE6$etherslibutils = require("ethers/lib/utils");
var $jXfE6$axios = require("axios");
function $parcel$exportWildcard(dest, source) {
Object.keys(source).forEach(function(key) {
if (key === 'default' || key === '__esModule' || dest.hasOwnProperty(key)) {
return;
}
Object.defineProperty(dest, key, {
enumerable: true,
get: function get() {
return source[key];
}
});
});
return dest;
}
function $parcel$export(e, n, v, s) {
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
}
function $parcel$interopDefault(a) {
return a && a.__esModule ? a.default : a;
}
var $03811f1a5629648d$exports = {};
$parcel$export($03811f1a5629648d$exports, "ReservoirClient", () => $03811f1a5629648d$export$d0c36b5db6a81704);
$parcel$export($03811f1a5629648d$exports, "getClient", () => $03811f1a5629648d$export$6bb76d6eba7e258c);
$parcel$export($03811f1a5629648d$exports, "createClient", () => $03811f1a5629648d$export$5d730b7aed1a3eb0);
var $d0cef1e583ae596a$exports = {};
$parcel$export($d0cef1e583ae596a$exports, "executeSteps", () => $b23c6475d0319dc3$export$21ece85d7636deb);
$parcel$export($d0cef1e583ae596a$exports, "setParams", () => $59bd71c643f9f8f4$export$dc1827290674c112);
$parcel$export($d0cef1e583ae596a$exports, "pollUntilOk", () => $76feafd37f5a93a4$export$d2c70568ef790b87);
$parcel$export($d0cef1e583ae596a$exports, "pollUntilHasData", () => $76feafd37f5a93a4$export$f014594cc879f602);
$parcel$export($d0cef1e583ae596a$exports, "isOpenSeaBanned", () => $6ba151369692c17e$export$feaa73ad8ed3f2b9);
async function $76feafd37f5a93a4$export$f014594cc879f602(request, dataParser) {
async function getData() {
let res = await (0, ($parcel$interopDefault($jXfE6$axios))).request(request);
return res.data;
}
const json = await getData();
// Check if the data exists
const dataExists = dataParser(json);
if (dataExists) return json;
// The response is still unchanged. Check again in five seconds
await new Promise((resolve)=>setTimeout(resolve, 5000));
await $76feafd37f5a93a4$export$f014594cc879f602(request, dataParser);
}
async function $76feafd37f5a93a4$export$d2c70568ef790b87(request, validate) {
const res1 = await (0, ($parcel$interopDefault($jXfE6$axios))).request(request);
if (!validate) validate = (res)=>res.status === 200;
// Check that the response from an endpoint updated
if (validate(res1)) return true;
else {
// The response is still unchanged. Check again in five seconds
await new Promise((resolve)=>setTimeout(resolve, 5000));
await $76feafd37f5a93a4$export$d2c70568ef790b87(request, validate);
}
}
function $59bd71c643f9f8f4$export$dc1827290674c112(url, query) {
Object.keys(query).map((key)=>{
var _a;
let value = query[key];
if (value !== undefined) {
if (Array.isArray(value)) value.forEach((item)=>{
url.searchParams.append(key, item);
});
else url.searchParams.append(key, (_a = query[key]) === null || _a === void 0 ? void 0 : _a.toString());
}
return url;
});
}
var $fc521934a32b4047$exports = {};
$fc521934a32b4047$exports = JSON.parse('{"name":"@reservoir0x/reservoir-kit-client","version":"0.2.5","description":"ReservoirKit is the official frontend kit to get you started building dApps with the ReservoirProtocol.","source":"src/index.ts","main":"dist/index.js","module":"dist/index.module.js","types":"dist/index.d.ts","author":"Reservoir Protocol","license":"MIT","files":["dist"],"scripts":{"clean":"rm -rf dist","version":"yarn version","version:package":"sh ../../scripts/package-version.sh","version:update":"yarn version ${0}; PACKAGE_VERSION=$(yarn version:package); git add -A; git commit -m \\"\uD83C\uDF89 Release client package v$PACKAGE_VERSION\\"; git push","syncApi":"npx openapi-typescript https://api.reservoir.tools/swagger.json --output ./src/types/api.ts","changelog":"node ../../scripts/generate-changelog.js package=client"},"repository":{"type":"git","url":"https://github.com/reservoirprotocol/reservoir-kit"},"sideEffects":false,"keywords":["nft","reservoir","reservoirkit","protocol","sdk"],"peerDependencies":{"ethers":"^5.6.1"},"dependencies":{"axios":"^0.27.2"},"publishConfig":{"access":"public"},"devDependencies":{"openapi-typescript":"^5.4.1"}}');
async function $b23c6475d0319dc3$export$21ece85d7636deb(request, signer, setState, newJson, expectedPrice) {
var _a1, _b1, _c;
try {
let json1 = newJson;
if (!request.headers) request.headers = {};
const client = (0, $03811f1a5629648d$export$6bb76d6eba7e258c)();
if (client === null || client === void 0 ? void 0 : client.apiKey) request.headers["x-api-key"] = client.apiKey;
if (client === null || client === void 0 ? void 0 : client.uiVersion) request.headers["x-rkui-version"] = client.uiVersion;
request.headers["x-rkc-version"] = (0, $fc521934a32b4047$exports.version);
if (!json1) {
const res = await (0, ($parcel$interopDefault($jXfE6$axios))).request(request);
json1 = res.data;
if (res.status !== 200) throw json1;
}
// Handle errors
if (json1.error || !json1.steps) throw json1;
const isBuy = (_a1 = request.url) === null || _a1 === void 0 ? void 0 : _a1.includes("/execute/buy");
const isSell = (_b1 = request.url) === null || _b1 === void 0 ? void 0 : _b1.includes("/execute/sell");
// Handle price changes to protect users from paying more
// than expected when buying and selling for less than expected
if (json1.path && expectedPrice) {
const quote = json1.path.reduce((total, path)=>{
total += path.quote || 0;
return total;
}, 0);
// Check if the user is selling
let error = null;
if (isSell && quote - expectedPrice < -0.00001) error = {
type: "price mismatch",
message: `The quoted price of ${quote} is less than the expected price of ${expectedPrice}`
};
// Check if the user is buying
if (isBuy && quote - expectedPrice > 0.00001) error = {
type: "price mismatch",
message: `The quoted price of ${quote} is greater than the expected price of ${expectedPrice}`
};
if (error) {
json1.steps[0].error = error.message;
json1.steps[0].errorData = json1.path;
setState([
...json1 === null || json1 === void 0 ? void 0 : json1.steps
]);
throw error;
}
}
// Update state on first call or recursion
setState([
...json1 === null || json1 === void 0 ? void 0 : json1.steps
]);
let incompleteStepIndex = -1;
let incompleteStepItemIndex = -1;
json1.steps.find((step, i)=>{
if (!step.items) return false;
incompleteStepItemIndex = step.items.findIndex((item)=>item.status == "incomplete");
if (incompleteStepItemIndex !== -1) {
incompleteStepIndex = i;
return true;
}
});
// There are no more incomplete steps
if (incompleteStepIndex === -1) return;
const step1 = json1.steps[incompleteStepIndex];
const stepItems = json1.steps[incompleteStepIndex].items;
if (!stepItems) return;
let { kind: kind } = step1;
let stepItem = stepItems[incompleteStepItemIndex];
// If step item is missing data, poll until it is ready
if (!stepItem.data) {
json1 = await (0, $76feafd37f5a93a4$export$f014594cc879f602)(request, (json)=>{
var _a, _b;
const data = json;
return ((_b = (_a = data === null || data === void 0 ? void 0 : data.steps) === null || _a === void 0 ? void 0 : _a[incompleteStepIndex].items) === null || _b === void 0 ? void 0 : _b[incompleteStepItemIndex].data) ? true : false;
});
if (!json1.steps || !json1.steps[incompleteStepIndex].items) throw json1;
const items = json1.steps[incompleteStepIndex].items;
if (!items || !items[incompleteStepItemIndex] || !items[incompleteStepItemIndex].data) throw json1;
stepItem = items[incompleteStepItemIndex];
}
const stepData = stepItem.data;
// Handle each step based on it's kind
switch(kind){
// Make an on-chain transaction
case "transaction":
{
const tx = await signer.sendTransaction(stepData);
if ((_c = json1.steps[incompleteStepIndex].items) === null || _c === void 0 ? void 0 : _c[incompleteStepItemIndex]) stepItem.txHash = tx.hash;
setState([
...json1 === null || json1 === void 0 ? void 0 : json1.steps
]);
await tx.wait();
//Implicitly poll the confirmation url to confirm the transaction went through
const confirmationUrl = new URL(`${client.apiBase}/transactions/${tx.hash}/synced/v1`);
const headers = {
"x-rkc-version": (0, $fc521934a32b4047$exports.version)
};
if (client === null || client === void 0 ? void 0 : client.apiKey) headers["x-api-key"] = client.apiKey;
if (client === null || client === void 0 ? void 0 : client.uiVersion) request.headers["x-rkui-version"] = client.uiVersion;
await (0, $76feafd37f5a93a4$export$d2c70568ef790b87)({
url: confirmationUrl.href,
method: "get",
headers: headers
}, (res)=>res && res.data.synced);
if (json1.steps.slice(incompleteStepIndex + 1).findIndex((step)=>step.kind === "transaction") === -1) //Confirm that on-chain tx has been picked up by the indexer for the last transaction
{
if (stepItem.txHash && (isSell || isBuy)) {
const indexerConfirmationUrl = new URL(`${client.apiBase}/sales/v3`);
const queryParams = {
txHash: stepItem.txHash
};
(0, $59bd71c643f9f8f4$export$dc1827290674c112)(indexerConfirmationUrl, queryParams);
await (0, $76feafd37f5a93a4$export$d2c70568ef790b87)({
url: indexerConfirmationUrl.href,
method: "get",
headers: headers
}, (res)=>{
if (res.status === 200) {
const data = res.data;
return data.sales && data.sales.length > 0 ? true : false;
}
return false;
});
}
}
break;
}
// Sign a message
case "signature":
{
let signature;
const signData = stepData["sign"];
const postData = stepData["post"];
if (signData) {
// Request user signature
if (signData.signatureKind === "eip191") {
if (signData.message.match(/0x[0-9a-fA-F]{64}/)) // If the message represents a hash, we need to convert it to raw bytes first
signature = await signer.signMessage((0, $jXfE6$etherslibutils.arrayify)(signData.message));
else signature = await signer.signMessage(signData.message);
} else if (signData.signatureKind === "eip712") signature = await signer._signTypedData(signData.domain, signData.types, signData.value);
if (signature) request.params = {
...request.params,
signature: signature
};
}
if (postData) {
const postOrderUrl = new URL(`${client.apiBase}${postData.endpoint}`);
try {
const getData = async function() {
const headers = {
"Content-Type": "application/json",
"x-rkc-version": (0, $fc521934a32b4047$exports.version)
};
if (client === null || client === void 0 ? void 0 : client.apiKey) headers["x-api-key"] = client.apiKey;
let response = await (0, ($parcel$interopDefault($jXfE6$axios))).post(postOrderUrl.href, JSON.stringify(postData.body), {
method: postData.method,
headers: headers,
params: request.params
});
return response;
};
const res = await getData();
if (res.status > 299 || res.status < 200) throw res.data;
stepItem.orderId = res.data.orderId;
setState([
...json1 === null || json1 === void 0 ? void 0 : json1.steps
]);
} catch (err) {
json1.steps[incompleteStepIndex].error = "Your order could not be posted.";
setState([
...json1 === null || json1 === void 0 ? void 0 : json1.steps
]);
throw err;
}
}
break;
}
default:
break;
}
delete step1.message;
stepItem.status = "complete";
// Recursively call executeSteps()
await $b23c6475d0319dc3$export$21ece85d7636deb(request, signer, setState, json1);
} catch (err) {
const error = new Error(err === null || err === void 0 ? void 0 : err.message);
console.error(error);
throw err;
}
}
async function $6ba151369692c17e$export$feaa73ad8ed3f2b9(contract, tokenId) {
const base = "https://api.opensea.io";
const url = new URL(`/api/v1/asset/${contract}/${tokenId}`, base);
const res = await (0, ($parcel$interopDefault($jXfE6$axios))).get(url.href);
const json = res.data;
const client = (0, $03811f1a5629648d$export$6bb76d6eba7e258c)();
const apiBase = client === null || client === void 0 ? void 0 : client.apiBase;
if (res.status === 200 && apiBase) {
const apiKey = client === null || client === void 0 ? void 0 : client.apiKey;
const headers = {
"Content-Type": "application/json",
"x-rkc-version": (0, $fc521934a32b4047$exports.version)
};
const body = {
token: `${contract}:${tokenId}`,
flag: !(json === null || json === void 0 ? void 0 : json.supports_wyvern) ? 1 : 0
};
if (apiKey) headers["x-api-key"] = apiKey;
if (client === null || client === void 0 ? void 0 : client.uiVersion) headers["x-rkui-version"] = client.uiVersion;
(0, ($parcel$interopDefault($jXfE6$axios))).post(`${apiBase}/tokens/flag/v1`, JSON.stringify(body), {
headers: headers
}).catch(()=>{});
}
return !(json === null || json === void 0 ? void 0 : json.supports_wyvern);
}
async function $11a4cdc026e9e2ff$export$ed27da83bcbea2e5(data) {
const { token: token , expectedPrice: expectedPrice , signer: signer , onProgress: onProgress } = data;
const taker = await signer.getAddress();
const client = (0, $03811f1a5629648d$export$6bb76d6eba7e258c)();
const options = data.options || {};
if (!client.apiBase) throw new ReferenceError("ReservoirClient missing configuration");
try {
const params = {
taker: taker,
token: `${token.contract}:${token.tokenId}`,
source: client.source || "",
...options
};
if (client.normalizeRoyalties !== undefined && params.normalizeRoyalties === undefined) params.normalizeRoyalties = client.normalizeRoyalties;
await (0, $b23c6475d0319dc3$export$21ece85d7636deb)({
url: `${client.apiBase}/execute/sell/v6`,
method: "post",
data: params
}, signer, onProgress, undefined, expectedPrice);
return true;
} catch (err) {
console.error(err);
throw err;
}
}
async function $2229bb7340cf2806$export$5e1997c166a16792(data1) {
const { tokens: tokens , orderIds: orderIds , rawOrders: rawOrders , expectedPrice: expectedPrice , signer: signer , onProgress: onProgress } = data1;
const taker = await signer.getAddress();
const client = (0, $03811f1a5629648d$export$6bb76d6eba7e258c)();
const options = data1.options || {};
if (!client.apiBase) throw new ReferenceError("ReservoirClient missing configuration");
if ((!tokens || !tokens.length) && (!data1.orderIds || !data1.orderIds.length) && !data1.rawOrders) {
console.debug(data1);
throw new ReferenceError("ReservoirClient missing data: At least one of the following is required, tokens, orderIds or rawOrders");
}
if (tokens && (orderIds || rawOrders) || orderIds && (tokens || rawOrders) || rawOrders && (orderIds || tokens)) {
console.debug(data1);
throw new ReferenceError("ReservoirClient conflicting data: tokens, orderIds and rawOrders are mutually exclusive");
}
try {
const params = {
taker: taker,
source: client.source || "",
...options
};
if (tokens) params.tokens = tokens === null || tokens === void 0 ? void 0 : tokens.map((token)=>`${token.contract}:${token.tokenId}`);
else if (orderIds) params.orderIds = orderIds;
else if (rawOrders) params.rawOrders = rawOrders;
if (client.normalizeRoyalties !== undefined && params.normalizeRoyalties === undefined) params.normalizeRoyalties = client.normalizeRoyalties;
await (0, $b23c6475d0319dc3$export$21ece85d7636deb)({
url: `${client.apiBase}/execute/buy/v6`,
method: "post",
data: params
}, signer, onProgress, undefined, expectedPrice);
return true;
} catch (err) {
if (tokens) {
const headers = {
"Content-Type": "application/json",
"x-rkc-version": (0, $fc521934a32b4047$exports.version)
};
if (client === null || client === void 0 ? void 0 : client.apiKey) headers["x-api-key"] = client.apiKey;
tokens.forEach((token)=>{
const data = {
router: "v6",
token: `${token.contract}:${token.tokenId}`
};
(0, ($parcel$interopDefault($jXfE6$axios))).post(`${client.apiBase}/tokens/simulate-floor/v1`, JSON.stringify(data), {
method: "POST",
headers: headers
});
});
}
throw err;
}
}
async function $be4562d70b364984$export$1d5423ff89b08a3c(data) {
const { id: id , signer: signer , onProgress: onProgress } = data;
const client = (0, $03811f1a5629648d$export$6bb76d6eba7e258c)();
const options = data.options || {};
if (!client.apiBase) throw new ReferenceError("ReservoirClient missing configuration");
try {
const params = {
id: id,
...options
};
await (0, $b23c6475d0319dc3$export$21ece85d7636deb)({
url: `${client.apiBase}/execute/cancel/v2`,
params: params
}, signer, onProgress);
return true;
} catch (err) {
console.error(err);
throw err;
}
}
async function $81493be96213ffb8$export$c5dd9dc6df16df31(data) {
const { listings: listings , signer: signer , onProgress: onProgress = ()=>{} , precheck: precheck } = data;
const client = (0, $03811f1a5629648d$export$6bb76d6eba7e258c)();
const maker = await signer.getAddress();
if (!client.apiBase) throw new ReferenceError("ReservoirClient missing configuration");
try {
const data = {
maker: maker,
source: client.source || ""
};
listings.forEach((listing)=>{
if (listing.orderbook === "reservoir" && client.marketplaceFee && client.marketplaceFeeRecipient && !("fees" in listing)) listing.fees = [
`${client.marketplaceFeeRecipient}:${client.marketplaceFee}`,
];
if (!("automatedRoyalties" in listing) && "automatedRoyalties" in client) listing.automatedRoyalties = client.automatedRoyalties;
});
data.params = listings;
const request = {
url: `${client.apiBase}/execute/list/v4`,
method: "post",
data: data,
headers: {
"x-rkc-version": (0, $fc521934a32b4047$exports.version)
}
};
if (precheck) {
if ((client === null || client === void 0 ? void 0 : client.apiKey) && request.headers) request.headers["x-api-key"] = client.apiKey;
if ((client === null || client === void 0 ? void 0 : client.uiVersion) && request.headers) request.headers["x-rkui-version"] = client.uiVersion;
const res = await (0, ($parcel$interopDefault($jXfE6$axios))).request(request);
if (res.status !== 200) throw res.data;
const data = res.data;
onProgress(data["steps"]);
return data["steps"];
} else await (0, $b23c6475d0319dc3$export$21ece85d7636deb)(request, signer, onProgress);
return true;
} catch (err) {
console.error(err);
throw err;
}
}
async function $a9677cf7712e310b$export$6d65a5902ff15306({ bids: bids , signer: signer , onProgress: onProgress }) {
const client = (0, $03811f1a5629648d$export$6bb76d6eba7e258c)();
const maker = await signer.getAddress();
if (!client.apiBase) throw new ReferenceError("ReservoirClient missing configuration");
try {
const data = {
maker: maker,
source: client.source || ""
};
bids.forEach((bid)=>{
if (!bid.token && !bid.collection && !bid.tokenSetId && (!bid.attributeKey || !bid.attributeValue)) throw {
message: "Some bid data is missing",
data: bid
};
if (bid.orderbook === "reservoir" && client.marketplaceFee && client.marketplaceFeeRecipient && !("fees" in bid)) bid.fees = [
`${client.marketplaceFeeRecipient}:${client.marketplaceFee}`,
];
if (!("automatedRoyalties" in bid) && "automatedRoyalties" in client) bid.automatedRoyalties = client.automatedRoyalties;
});
data.params = bids;
await (0, $b23c6475d0319dc3$export$21ece85d7636deb)({
url: `${client.apiBase}/execute/bid/v4`,
method: "post",
data: data
}, signer, onProgress);
return true;
} catch (err) {
console.error(err);
throw err;
}
}
const $1b90daf9645955b9$var$actions = {
acceptOffer: $11a4cdc026e9e2ff$export$ed27da83bcbea2e5,
buyToken: $2229bb7340cf2806$export$5e1997c166a16792,
cancelOrder: $be4562d70b364984$export$1d5423ff89b08a3c,
listToken: $81493be96213ffb8$export$c5dd9dc6df16df31,
placeBid: $a9677cf7712e310b$export$6d65a5902ff15306
};
var $1b90daf9645955b9$export$2e2bcd8739ae039 = $1b90daf9645955b9$var$actions;
let $03811f1a5629648d$var$_client;
class $03811f1a5629648d$export$d0c36b5db6a81704 {
constructor(options){
this.utils = {
...$d0cef1e583ae596a$exports
};
this.actions = (0, $1b90daf9645955b9$export$2e2bcd8739ae039);
this.version = (0, $fc521934a32b4047$exports.version);
this.apiKey = options.apiKey;
this.uiVersion = options.uiVersion;
this.apiBase = options.apiBase;
this.automatedRoyalties = options.automatedRoyalties;
this.marketplaceFee = options.marketplaceFee;
this.marketplaceFeeRecipient = options.marketplaceFeeRecipient;
this.normalizeRoyalties = options.normalizeRoyalties;
if (!options.source) {
if (typeof window !== "undefined") {
let host = location.hostname;
if (host.indexOf("www.") === 0) host = host.replace("www.", "");
this.source = host;
console.warn("ReservoirKit automatically generated a source based on the url, we recommend providing a source when initializing ReservoirKit. Refer to our docs for steps on how to do this: http://docs.reservoir.tools");
}
} else this.source = options.source;
}
configure(options) {
this.source = options.source ? options.source : this.source;
this.apiKey = options.apiKey ? options.apiKey : this.apiKey;
this.uiVersion = options.uiVersion ? options.uiVersion : this.uiVersion;
this.apiBase = options.apiBase ? options.apiBase : this.apiBase;
this.marketplaceFee = options.marketplaceFee ? options.marketplaceFee : this.marketplaceFee;
this.marketplaceFeeRecipient = options.marketplaceFeeRecipient ? options.marketplaceFeeRecipient : this.marketplaceFeeRecipient;
this.automatedRoyalties = options.automatedRoyalties;
this.normalizeRoyalties = options.normalizeRoyalties !== undefined ? options.normalizeRoyalties : this.normalizeRoyalties;
}
}
function $03811f1a5629648d$export$6bb76d6eba7e258c() {
//throw an error
return $03811f1a5629648d$var$_client;
}
function $03811f1a5629648d$export$5d730b7aed1a3eb0(options) {
if (!$03811f1a5629648d$var$_client) $03811f1a5629648d$var$_client = new $03811f1a5629648d$export$d0c36b5db6a81704(options);
else $03811f1a5629648d$var$_client.configure(options);
return $03811f1a5629648d$var$_client;
}
var $7656623fb3976920$exports = {};
var $f3d6fe14cc8c05dc$exports = {};
$parcel$exportWildcard($7656623fb3976920$exports, $f3d6fe14cc8c05dc$exports);
$parcel$exportWildcard(module.exports, $03811f1a5629648d$exports);
$parcel$exportWildcard(module.exports, $d0cef1e583ae596a$exports);
$parcel$exportWildcard(module.exports, $7656623fb3976920$exports);
//# sourceMappingURL=index.js.map