gemsdkbeta
Version:
JavaScript SDK for the GEM swap
973 lines • 42.5 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 __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 _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNonCompliantApprovalAddress = exports.onDeprecated = exports.validateAndFormatWalletAddress = exports.delay = exports.assignOrdersToSides = exports.getOrderHash = exports.getWyvernBundle = exports.getWyvernAsset = exports.estimateCurrentPrice = exports.getTransferFeeSettings = exports.getCurrentGasPrice = exports.estimateGas = exports.rawCall = exports.sendRawTransaction = exports.makeBigNumber = exports.isContractAddress = exports.personalSignAsync = exports.orderToJSON = exports.orderFromJSON = exports.tokenFromJSON = exports.collectionFromJSON = exports.assetContractFromJSON = exports.assetBundleFromJSON = exports.userFromJSON = exports.accountFromJSON = exports.transactionFromJSON = exports.assetEventFromJSON = exports.assetFromJSON = exports.confirmTransaction = exports.promisifyCall = exports.annotateERC20TransferABI = exports.annotateERC721TransferABI = exports.WyvernProtocol = void 0;
var bignumber_js_1 = require("bignumber.js");
var wyvern_js_1 = require("wyvern-js");
Object.defineProperty(exports, "WyvernProtocol", { enumerable: true, get: function () { return wyvern_js_1.WyvernProtocol; } });
var ethUtil = require("ethereumjs-util");
var _ = require("lodash");
var Web3 = require("web3");
var types_1 = require("wyvern-schemas/dist/types");
var contracts_1 = require("../contracts");
var types_2 = require("../types");
var constants_1 = require("../constants");
var Proxy_1 = require("../abi/Proxy");
var annotateERC721TransferABI = function (asset) { return ({
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address",
"kind": types_1.FunctionInputKind.Replaceable
},
{
"name": "_tokenId",
"type": "uint256",
"kind": types_1.FunctionInputKind.Asset,
"value": asset.id
}
],
"target": asset.address,
"name": "transfer",
"outputs": [],
"payable": false,
"stateMutability": types_1.StateMutability.Nonpayable,
"type": Web3.AbiType.Function
}); };
exports.annotateERC721TransferABI = annotateERC721TransferABI;
var annotateERC20TransferABI = function (asset) { return ({
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address",
"kind": types_1.FunctionInputKind.Replaceable
},
{
"name": "_amount",
"type": "uint256",
"kind": types_1.FunctionInputKind.Count,
"value": asset.quantity
}
],
"target": asset.address,
"name": "transfer",
"outputs": [
{
"name": "success",
"type": "bool",
"kind": types_1.FunctionOutputKind.Other
}
],
"payable": false,
"stateMutability": types_1.StateMutability.Nonpayable,
"type": Web3.AbiType.Function
}); };
exports.annotateERC20TransferABI = annotateERC20TransferABI;
var SCHEMA_NAME_TO_ASSET_CONTRACT_TYPE = (_a = {},
_a[types_2.WyvernSchemaName.ERC721] = types_2.AssetContractType.NonFungible,
_a[types_2.WyvernSchemaName.ERC721v3] = types_2.AssetContractType.NonFungible,
_a[types_2.WyvernSchemaName.ERC1155] = types_2.AssetContractType.SemiFungible,
_a[types_2.WyvernSchemaName.ERC20] = types_2.AssetContractType.Fungible,
_a[types_2.WyvernSchemaName.LegacyEnjin] = types_2.AssetContractType.SemiFungible,
_a[types_2.WyvernSchemaName.ENSShortNameAuction] = types_2.AssetContractType.NonFungible,
_a);
// OTHER
var txCallbacks = {};
/**
* Promisify a callback-syntax web3 function
* @param inner callback function that accepts a Web3 callback function and passes
* it to the Web3 function
*/
function promisify(inner) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
return inner(function (err, res) {
if (err) {
reject(err);
}
resolve(res);
});
})];
});
});
}
/**
* Promisify a call a method on a contract,
* handling Parity errors. Returns '0x' if error.
* Note that if T is not "string", this may return a falsey
* value when the contract doesn't support the method (e.g. `isApprovedForAll`).
* @param callback An anonymous function that takes a web3 callback
* and returns a Web3 Contract's call result, e.g. `c => erc721.ownerOf(3, c)`
* @param onError callback when user denies transaction
*/
function promisifyCall(callback, onError) {
return __awaiter(this, void 0, void 0, function () {
var result, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, promisify(callback)];
case 1:
result = _a.sent();
if (result == '0x') {
// Geth compatibility
return [2 /*return*/, undefined];
}
return [2 /*return*/, result];
case 2:
error_1 = _a.sent();
// Probably method not found, and web3 is a Parity node
if (onError) {
// @ts-ignore
onError(error_1);
}
else {
console.error(error_1);
}
return [2 /*return*/, undefined];
case 3: return [2 /*return*/];
}
});
});
}
exports.promisifyCall = promisifyCall;
var track = function (web3, txHash, onFinalized) {
if (txCallbacks[txHash]) {
txCallbacks[txHash].push(onFinalized);
}
else {
txCallbacks[txHash] = [onFinalized];
var poll_1 = function () { return __awaiter(void 0, void 0, void 0, function () {
var tx, receipt, status_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, promisify(function (c) { return web3.eth.getTransaction(txHash, c); })];
case 1:
tx = _a.sent();
if (!(tx && tx.blockHash && tx.blockHash !== constants_1.NULL_BLOCK_HASH)) return [3 /*break*/, 3];
return [4 /*yield*/, promisify(function (c) { return web3.eth.getTransactionReceipt(txHash, c); })];
case 2:
receipt = _a.sent();
if (!receipt) {
// Hack: assume success if no receipt
console.warn('No receipt found for ', txHash);
}
status_1 = receipt
? parseInt((receipt.status || "0").toString()) == 1
: true;
txCallbacks[txHash].map(function (f) { return f(status_1); });
delete txCallbacks[txHash];
return [3 /*break*/, 4];
case 3:
setTimeout(poll_1, 1000);
_a.label = 4;
case 4: return [2 /*return*/];
}
});
}); };
poll_1().catch();
}
};
var confirmTransaction = function (web3, txHash) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
track(web3, txHash, function (didSucceed) {
if (didSucceed) {
resolve("Transaction complete!");
}
else {
reject(new Error("Transaction failed :( You might have already completed this action. See more on the mainnet at etherscan.io/tx/" + txHash));
}
});
})];
});
}); };
exports.confirmTransaction = confirmTransaction;
var assetFromJSON = function (asset) {
var isAnimated = asset.image_url && asset.image_url.endsWith('.gif');
var isSvg = asset.image_url && asset.image_url.endsWith('.svg');
var fromJSON = {
tokenId: asset.token_id.toString(),
tokenAddress: asset.asset_contract.address,
name: asset.name,
description: asset.description,
owner: asset.owner,
assetContract: exports.assetContractFromJSON(asset.asset_contract),
collection: exports.collectionFromJSON(asset.collection),
orders: asset.orders ? asset.orders.map(exports.orderFromJSON) : null,
sellOrders: asset.sell_orders ? asset.sell_orders.map(exports.orderFromJSON) : null,
buyOrders: asset.buy_orders ? asset.buy_orders.map(exports.orderFromJSON) : null,
isPresale: asset.is_presale,
// Don't use previews if it's a special image
imageUrl: isAnimated || isSvg
? asset.image_url
: (asset.image_preview_url || asset.image_url),
imagePreviewUrl: asset.image_preview_url,
imageUrlOriginal: asset.image_original_url,
imageUrlThumbnail: asset.image_thumbnail_url,
externalLink: asset.external_link,
openseaLink: asset.permalink,
traits: asset.traits,
numSales: asset.num_sales,
lastSale: asset.last_sale ? exports.assetEventFromJSON(asset.last_sale) : null,
backgroundColor: asset.background_color ? "#" + asset.background_color : null,
transferFee: asset.transfer_fee
? makeBigNumber(asset.transfer_fee)
: null,
transferFeePaymentToken: asset.transfer_fee_payment_token
? exports.tokenFromJSON(asset.transfer_fee_payment_token)
: null,
};
// If orders were included, put them in sell/buy order groups
if (fromJSON.orders && !fromJSON.sellOrders) {
fromJSON.sellOrders = fromJSON.orders.filter(function (o) { return o.side == types_2.OrderSide.Sell; });
}
if (fromJSON.orders && !fromJSON.buyOrders) {
fromJSON.buyOrders = fromJSON.orders.filter(function (o) { return o.side == types_2.OrderSide.Buy; });
}
return fromJSON;
};
exports.assetFromJSON = assetFromJSON;
var assetEventFromJSON = function (assetEvent) {
return {
eventType: assetEvent.event_type,
eventTimestamp: assetEvent.event_timestamp,
auctionType: assetEvent.auction_type,
totalPrice: assetEvent.total_price,
transaction: assetEvent.transaction ? exports.transactionFromJSON(assetEvent.transaction) : null,
paymentToken: assetEvent.payment_token ? exports.tokenFromJSON(assetEvent.payment_token) : null,
};
};
exports.assetEventFromJSON = assetEventFromJSON;
var transactionFromJSON = function (transaction) {
return {
fromAccount: exports.accountFromJSON(transaction.from_account),
toAccount: exports.accountFromJSON(transaction.to_account),
createdDate: new Date(transaction.created_date + "Z"),
modifiedDate: new Date(transaction.modified_date + "Z"),
transactionHash: transaction.transaction_hash,
transactionIndex: transaction.transaction_index,
blockNumber: transaction.block_number,
blockHash: transaction.block_hash,
timestamp: new Date(transaction.timestamp + "Z"),
};
};
exports.transactionFromJSON = transactionFromJSON;
var accountFromJSON = function (account) {
return {
address: account.address,
config: account.config,
profileImgUrl: account.profile_img_url,
user: account.user ? exports.userFromJSON(account.user) : null
};
};
exports.accountFromJSON = accountFromJSON;
var userFromJSON = function (user) {
return {
username: user.username
};
};
exports.userFromJSON = userFromJSON;
var assetBundleFromJSON = function (asset_bundle) {
var fromJSON = {
maker: asset_bundle.maker,
assets: asset_bundle.assets.map(exports.assetFromJSON),
assetContract: asset_bundle.asset_contract
? exports.assetContractFromJSON(asset_bundle.asset_contract)
: undefined,
name: asset_bundle.name,
slug: asset_bundle.slug,
description: asset_bundle.description,
externalLink: asset_bundle.external_link,
permalink: asset_bundle.permalink,
sellOrders: asset_bundle.sell_orders ? asset_bundle.sell_orders.map(exports.orderFromJSON) : null
};
return fromJSON;
};
exports.assetBundleFromJSON = assetBundleFromJSON;
var assetContractFromJSON = function (asset_contract) {
return {
name: asset_contract.name,
description: asset_contract.description,
type: asset_contract.asset_contract_type,
schemaName: asset_contract.schema_name,
address: asset_contract.address,
tokenSymbol: asset_contract.symbol,
buyerFeeBasisPoints: +asset_contract.buyer_fee_basis_points,
sellerFeeBasisPoints: +asset_contract.seller_fee_basis_points,
openseaBuyerFeeBasisPoints: +asset_contract.opensea_buyer_fee_basis_points,
openseaSellerFeeBasisPoints: +asset_contract.opensea_seller_fee_basis_points,
devBuyerFeeBasisPoints: +asset_contract.dev_buyer_fee_basis_points,
devSellerFeeBasisPoints: +asset_contract.dev_seller_fee_basis_points,
imageUrl: asset_contract.image_url,
externalLink: asset_contract.external_link,
wikiLink: asset_contract.wiki_link,
};
};
exports.assetContractFromJSON = assetContractFromJSON;
var collectionFromJSON = function (collection) {
var createdDate = new Date(collection.created_date + "Z");
return {
createdDate: createdDate,
name: collection.name,
description: collection.description,
slug: collection.slug,
editors: collection.editors,
hidden: collection.hidden,
featured: collection.featured,
featuredImageUrl: collection.featured_image_url,
displayData: collection.display_data,
paymentTokens: (collection.payment_tokens || []).map(exports.tokenFromJSON),
openseaBuyerFeeBasisPoints: +collection.opensea_buyer_fee_basis_points,
openseaSellerFeeBasisPoints: +collection.opensea_seller_fee_basis_points,
devBuyerFeeBasisPoints: +collection.dev_buyer_fee_basis_points,
devSellerFeeBasisPoints: +collection.dev_seller_fee_basis_points,
payoutAddress: collection.payout_address,
imageUrl: collection.image_url,
largeImageUrl: collection.large_image_url,
stats: collection.stats,
traitStats: collection.traits,
externalLink: collection.external_url,
wikiLink: collection.wiki_url,
};
};
exports.collectionFromJSON = collectionFromJSON;
var tokenFromJSON = function (token) {
var fromJSON = {
name: token.name,
symbol: token.symbol,
decimals: token.decimals,
address: token.address,
imageUrl: token.image_url,
ethPrice: token.eth_price,
usdPrice: token.usd_price,
};
return fromJSON;
};
exports.tokenFromJSON = tokenFromJSON;
var orderFromJSON = function (order) {
var createdDate = new Date(order.created_date + "Z");
var fromJSON = {
hash: order.order_hash || order.hash,
cancelledOrFinalized: order.cancelled || order.finalized,
markedInvalid: order.marked_invalid,
metadata: order.metadata,
quantity: new bignumber_js_1.default(order.quantity || 1),
exchange: order.exchange,
makerAccount: order.maker,
takerAccount: order.taker,
// Use string address to conform to Wyvern Order schema
maker: order.maker.address,
taker: order.taker.address,
makerRelayerFee: new bignumber_js_1.default(order.maker_relayer_fee),
takerRelayerFee: new bignumber_js_1.default(order.taker_relayer_fee),
makerProtocolFee: new bignumber_js_1.default(order.maker_protocol_fee),
takerProtocolFee: new bignumber_js_1.default(order.taker_protocol_fee),
makerReferrerFee: new bignumber_js_1.default(order.maker_referrer_fee || 0),
waitingForBestCounterOrder: order.fee_recipient.address == constants_1.NULL_ADDRESS,
feeMethod: order.fee_method,
feeRecipientAccount: order.fee_recipient,
feeRecipient: order.fee_recipient.address,
side: order.side,
saleKind: order.sale_kind,
target: order.target,
howToCall: order.how_to_call,
calldata: order.calldata,
replacementPattern: order.replacement_pattern,
staticTarget: order.static_target,
staticExtradata: order.static_extradata,
paymentToken: order.payment_token,
basePrice: new bignumber_js_1.default(order.base_price),
extra: new bignumber_js_1.default(order.extra),
currentBounty: new bignumber_js_1.default(order.current_bounty || 0),
currentPrice: new bignumber_js_1.default(order.current_price || 0),
createdTime: new bignumber_js_1.default(Math.round(createdDate.getTime() / 1000)),
listingTime: new bignumber_js_1.default(order.listing_time),
expirationTime: new bignumber_js_1.default(order.expiration_time),
salt: new bignumber_js_1.default(order.salt),
v: parseInt(order.v),
r: order.r,
s: order.s,
paymentTokenContract: order.payment_token_contract ? exports.tokenFromJSON(order.payment_token_contract) : undefined,
asset: order.asset ? exports.assetFromJSON(order.asset) : undefined,
assetBundle: order.asset_bundle ? exports.assetBundleFromJSON(order.asset_bundle) : undefined,
};
// Use client-side price calc, to account for buyer fee (not added by server) and latency
fromJSON.currentPrice = estimateCurrentPrice(fromJSON);
return fromJSON;
};
exports.orderFromJSON = orderFromJSON;
/**
* Convert an order to JSON, hashing it as well if necessary
* @param order order (hashed or unhashed)
*/
var orderToJSON = function (order) {
var asJSON = {
exchange: order.exchange.toLowerCase(),
maker: order.maker.toLowerCase(),
taker: order.taker.toLowerCase(),
makerRelayerFee: order.makerRelayerFee.toString(),
takerRelayerFee: order.takerRelayerFee.toString(),
makerProtocolFee: order.makerProtocolFee.toString(),
takerProtocolFee: order.takerProtocolFee.toString(),
makerReferrerFee: order.makerReferrerFee.toString(),
feeMethod: order.feeMethod,
feeRecipient: order.feeRecipient.toLowerCase(),
side: order.side,
saleKind: order.saleKind,
target: order.target.toLowerCase(),
howToCall: order.howToCall,
calldata: order.calldata,
replacementPattern: order.replacementPattern,
staticTarget: order.staticTarget.toLowerCase(),
staticExtradata: order.staticExtradata,
paymentToken: order.paymentToken.toLowerCase(),
quantity: order.quantity.toString(),
basePrice: order.basePrice.toString(),
englishAuctionReservePrice: order.englishAuctionReservePrice ? order.englishAuctionReservePrice.toString() : undefined,
extra: order.extra.toString(),
createdTime: order.createdTime
? order.createdTime.toString()
: undefined,
listingTime: order.listingTime.toString(),
expirationTime: order.expirationTime.toString(),
salt: order.salt.toString(),
metadata: order.metadata,
v: order.v,
r: order.r,
s: order.s,
hash: order.hash
};
return asJSON;
};
exports.orderToJSON = orderToJSON;
/**
* Sign messages using web3 personal signatures
* @param web3 Web3 instance
* @param message message to sign
* @param signerAddress web3 address signing the message
* @returns A signature if provider can sign, otherwise null
*/
function personalSignAsync(web3, message, signerAddress) {
return __awaiter(this, void 0, void 0, function () {
var signature, error;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, promisify(function (c) { return web3.currentProvider.sendAsync({
method: 'personal_sign',
params: [message, signerAddress],
from: signerAddress,
id: Math.ceil(Date.now() / 1000) + 30
}, c); })];
case 1:
signature = _a.sent();
error = signature.error;
if (error) {
throw new Error(error);
}
return [2 /*return*/, parseSignatureHex(signature.result)];
}
});
});
}
exports.personalSignAsync = personalSignAsync;
/**
* Checks whether a given address contains any code
* @param web3 Web3 instance
* @param address input address
*/
function isContractAddress(web3, address) {
return __awaiter(this, void 0, void 0, function () {
var code;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, promisify(function (c) { return web3.eth.getCode(address, c); })];
case 1:
code = _a.sent();
return [2 /*return*/, code !== '0x'];
}
});
});
}
exports.isContractAddress = isContractAddress;
/**
* Special fixes for making BigNumbers using web3 results
* @param arg An arg or the result of a web3 call to turn into a BigNumber
*/
function makeBigNumber(arg) {
// Zero sometimes returned as 0x from contracts
if (arg === '0x') {
arg = 0;
}
// fix "new BigNumber() number type has more than 15 significant digits"
arg = arg.toString();
return new bignumber_js_1.default(arg);
}
exports.makeBigNumber = makeBigNumber;
/**
* Send a transaction to the blockchain and optionally confirm it
* @param web3 Web3 instance
* @param param0 __namedParameters
* @param from address sending transaction
* @param to destination contract address
* @param data data to send to contract
* @param gasPrice gas price to use. If unspecified, uses web3 default (mean gas price)
* @param value value in ETH to send with data. Defaults to 0
* @param onError callback when user denies transaction
*/
function sendRawTransaction(web3, _a, onError) {
var from = _a.from, to = _a.to, data = _a.data, gasPrice = _a.gasPrice, _b = _a.value, value = _b === void 0 ? 0 : _b, gas = _a.gas;
return __awaiter(this, void 0, void 0, function () {
var txHashRes, error_2;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(gas == null)) return [3 /*break*/, 2];
return [4 /*yield*/, estimateGas(web3, { from: from, to: to, data: data, value: value })];
case 1:
// This gas cannot be increased due to an ethjs error
gas = _c.sent();
_c.label = 2;
case 2:
_c.trys.push([2, 4, , 5]);
return [4 /*yield*/, promisify(function (c) { return web3.eth.sendTransaction({
from: from,
to: to,
value: value,
data: data,
gas: gas,
gasPrice: gasPrice
}, c); })];
case 3:
txHashRes = _c.sent();
return [2 /*return*/, txHashRes.toString()];
case 4:
error_2 = _c.sent();
// @ts-ignore
onError(error_2);
throw error_2;
case 5: return [2 /*return*/];
}
});
});
}
exports.sendRawTransaction = sendRawTransaction;
/**
* Call a method on a contract, sending arbitrary data and
* handling Parity errors. Returns '0x' if error.
* @param web3 Web3 instance
* @param param0 __namedParameters
* @param from address sending call
* @param to destination contract address
* @param data data to send to contract
* @param onError callback when user denies transaction
*/
function rawCall(web3, _a, onError) {
var from = _a.from, to = _a.to, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var result, error_3;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
return [4 /*yield*/, promisify(function (c) { return web3.eth.call({
from: from,
to: to,
data: data
}, c); })];
case 1:
result = _b.sent();
return [2 /*return*/, result];
case 2:
error_3 = _b.sent();
// Probably method not found, and web3 is a Parity node
if (onError) {
// @ts-ignore
onError(error_3);
}
// Backwards compatibility with Geth nodes
return [2 /*return*/, '0x'];
case 3: return [2 /*return*/];
}
});
});
}
exports.rawCall = rawCall;
/**
* Estimate Gas usage for a transaction
* @param web3 Web3 instance
* @param from address sending transaction
* @param to destination contract address
* @param data data to send to contract
* @param value value in ETH to send with data
*/
function estimateGas(web3, _a) {
var from = _a.from, to = _a.to, data = _a.data, _b = _a.value, value = _b === void 0 ? 0 : _b;
return __awaiter(this, void 0, void 0, function () {
var amount;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, promisify(function (c) { return web3.eth.estimateGas({
from: from,
to: to,
value: value,
data: data,
}, c); })];
case 1:
amount = _c.sent();
return [2 /*return*/, amount];
}
});
});
}
exports.estimateGas = estimateGas;
/**
* Get mean gas price for sending a txn, in wei
* @param web3 Web3 instance
*/
function getCurrentGasPrice(web3) {
return __awaiter(this, void 0, void 0, function () {
var meanGas;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, promisify(function (c) { return web3.eth.getGasPrice(c); })];
case 1:
meanGas = _a.sent();
return [2 /*return*/, meanGas];
}
});
});
}
exports.getCurrentGasPrice = getCurrentGasPrice;
/**
* Get current transfer fees for an asset
* @param web3 Web3 instance
* @param asset The asset to check for transfer fees
*/
function getTransferFeeSettings(web3, _a) {
var asset = _a.asset, accountAddress = _a.accountAddress;
return __awaiter(this, void 0, void 0, function () {
var transferFee, transferFeeTokenAddress, feeContract_1, params;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!(asset.tokenAddress.toLowerCase() == constants_1.ENJIN_ADDRESS.toLowerCase())) return [3 /*break*/, 2];
feeContract_1 = web3.eth.contract(contracts_1.ERC1155).at(asset.tokenAddress);
return [4 /*yield*/, promisifyCall(function (c) { return feeContract_1.transferSettings(asset.tokenId, { from: accountAddress }, c); })];
case 1:
params = _b.sent();
if (params) {
transferFee = makeBigNumber(params[3]);
if (params[2] == 0) {
transferFeeTokenAddress = constants_1.ENJIN_COIN_ADDRESS;
}
}
_b.label = 2;
case 2: return [2 /*return*/, { transferFee: transferFee, transferFeeTokenAddress: transferFeeTokenAddress }];
}
});
});
}
exports.getTransferFeeSettings = getTransferFeeSettings;
// sourced from 0x.js:
// https://github.com/ProjectWyvern/wyvern-js/blob/39999cb93ce5d80ea90b4382182d1bd4339a9c6c/src/utils/signature_utils.ts
function parseSignatureHex(signature) {
// HACK: There is no consensus on whether the signatureHex string should be formatted as
// v + r + s OR r + s + v, and different clients (even different versions of the same client)
// return the signature params in different orders. In order to support all client implementations,
// we parse the signature in both ways, and evaluate if either one is a valid signature.
var validVParamValues = [27, 28];
var ecSignatureRSV = _parseSignatureHexAsRSV(signature);
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
return ecSignatureRSV;
}
// For older clients
var ecSignatureVRS = _parseSignatureHexAsVRS(signature);
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
return ecSignatureVRS;
}
throw new Error('Invalid signature');
function _parseSignatureHexAsVRS(signatureHex) {
var signatureBuffer = ethUtil.toBuffer(signatureHex);
var v = signatureBuffer[0];
if (v < 27) {
v += 27;
}
var r = signatureBuffer.slice(1, 33);
var s = signatureBuffer.slice(33, 65);
var ecSignature = {
v: v,
r: ethUtil.bufferToHex(r),
s: ethUtil.bufferToHex(s),
};
return ecSignature;
}
function _parseSignatureHexAsRSV(signatureHex) {
var _a = ethUtil.fromRpcSig(signatureHex), v = _a.v, r = _a.r, s = _a.s;
var ecSignature = {
v: v,
r: ethUtil.bufferToHex(r),
s: ethUtil.bufferToHex(s),
};
return ecSignature;
}
}
/**
* Estimates the price of an order
* @param order The order to estimate price on
* @param secondsToBacktrack The number of seconds to subtract on current time,
* to fix race conditions
* @param shouldRoundUp Whether to round up fractional wei
*/
function estimateCurrentPrice(order, secondsToBacktrack, shouldRoundUp) {
if (secondsToBacktrack === void 0) { secondsToBacktrack = 30; }
if (shouldRoundUp === void 0) { shouldRoundUp = true; }
var basePrice = order.basePrice, listingTime = order.listingTime, expirationTime = order.expirationTime, extra = order.extra;
var side = order.side, takerRelayerFee = order.takerRelayerFee, saleKind = order.saleKind;
var now = new bignumber_js_1.default(Math.round(Date.now() / 1000)).minus(secondsToBacktrack);
basePrice = new bignumber_js_1.default(basePrice);
listingTime = new bignumber_js_1.default(listingTime);
expirationTime = new bignumber_js_1.default(expirationTime);
extra = new bignumber_js_1.default(extra);
var exactPrice = basePrice;
if (saleKind === types_2.SaleKind.FixedPrice) {
// Do nothing, price is correct
}
else if (saleKind === types_2.SaleKind.DutchAuction) {
var diff = extra.times(now.minus(listingTime))
.dividedBy(expirationTime.minus(listingTime));
exactPrice = side == types_2.OrderSide.Sell
/* Sell-side - start price: basePrice. End price: basePrice - extra. */
? basePrice.minus(diff)
/* Buy-side - start price: basePrice. End price: basePrice + extra. */
: basePrice.plus(diff);
}
// Add taker fee only for buyers
if (side === types_2.OrderSide.Sell && !order.waitingForBestCounterOrder) {
// Buyer fee increases sale price
exactPrice = exactPrice.times(+takerRelayerFee / constants_1.INVERSE_BASIS_POINT + 1);
}
return shouldRoundUp ? exactPrice.ceil() : exactPrice;
}
exports.estimateCurrentPrice = estimateCurrentPrice;
/**
* Get the Wyvern representation of a fungible asset
* @param schema The WyvernSchema needed to access this asset
* @param asset The asset to trade
* @param quantity The number of items to trade
*/
function getWyvernAsset(schema, asset, quantity) {
if (quantity === void 0) { quantity = new bignumber_js_1.default(1); }
var tokenId = asset.tokenId != null
? asset.tokenId.toString()
: undefined;
return schema.assetFromFields({
'ID': tokenId,
'Quantity': quantity.toString(),
'Address': asset.tokenAddress.toLowerCase(),
'Name': asset.name
});
}
exports.getWyvernAsset = getWyvernAsset;
/**
* Get the Wyvern representation of a group of assets
* Sort order is enforced here. Throws if there's a duplicate.
* @param assets Assets to bundle
* @param schemas The WyvernSchemas needed to access each asset, respectively
* @param quantities The quantity of each asset to bundle, respectively
*/
function getWyvernBundle(assets, schemas, quantities) {
if (assets.length != quantities.length) {
throw new Error("Bundle must have a quantity for every asset");
}
if (assets.length != schemas.length) {
throw new Error("Bundle must have a schema for every asset");
}
var wyAssets = assets.map(function (asset, i) { return getWyvernAsset(schemas[i], asset, quantities[i]); });
var sorters = [
function (assetAndSchema) { return assetAndSchema.asset.address; },
function (assetAndSchema) { return assetAndSchema.asset.id || 0; }
];
var wyAssetsAndSchemas = wyAssets.map(function (asset, i) { return ({
asset: asset,
schema: schemas[i].name
}); });
var uniqueAssets = _.uniqBy(wyAssetsAndSchemas, function (group) { return sorters[0](group) + "-" + sorters[1](group); });
if (uniqueAssets.length != wyAssetsAndSchemas.length) {
throw new Error("Bundle can't contain duplicate assets");
}
var sortedWyAssetsAndSchemas = _.sortBy(wyAssetsAndSchemas, sorters);
return {
assets: sortedWyAssetsAndSchemas.map(function (group) { return group.asset; }),
schemas: sortedWyAssetsAndSchemas.map(function (group) { return group.schema; }),
};
}
exports.getWyvernBundle = getWyvernBundle;
/**
* Get the non-prefixed hash for the order
* (Fixes a Wyvern typescript issue and casing issue)
* @param order order to hash
*/
function getOrderHash(order) {
var orderWithStringTypes = __assign(__assign({}, order), { maker: order.maker.toLowerCase(), taker: order.taker.toLowerCase(), feeRecipient: order.feeRecipient.toLowerCase(), side: order.side.toString(), saleKind: order.saleKind.toString(), howToCall: order.howToCall.toString(), feeMethod: order.feeMethod.toString() });
return wyvern_js_1.WyvernProtocol.getOrderHashHex(orderWithStringTypes);
}
exports.getOrderHash = getOrderHash;
/**
* Assign an order and a new matching order to their buy/sell sides
* @param order Original order
* @param matchingOrder The result of _makeMatchingOrder
*/
function assignOrdersToSides(order, matchingOrder) {
var isSellOrder = order.side == types_2.OrderSide.Sell;
var buy;
var sell;
if (!isSellOrder) {
buy = order;
sell = __assign(__assign({}, matchingOrder), { v: buy.v, r: buy.r, s: buy.s });
}
else {
sell = order;
buy = __assign(__assign({}, matchingOrder), { v: sell.v, r: sell.r, s: sell.s });
}
return { buy: buy, sell: sell };
}
exports.assignOrdersToSides = assignOrdersToSides;
// BROKEN
// TODO fix this calldata for buy orders
function canSettleOrder(client, order, matchingOrder) {
return __awaiter(this, void 0, void 0, function () {
var calldata, seller, proxy, contract;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
calldata = order.calldata.slice(0, 98) + "1111111111111111111111111111111111111111" + order.calldata.slice(138);
seller = order.side == types_2.OrderSide.Buy ? matchingOrder.maker : order.maker;
return [4 /*yield*/, client._getProxy(seller)];
case 1:
proxy = _a.sent();
if (!proxy) {
console.warn("No proxy found for seller " + seller);
return [2 /*return*/, false];
}
contract = (client.web3.eth.contract([Proxy_1.proxyABI])).at(proxy);
return [2 /*return*/, promisify(function (c) {
return contract.proxy.call(order.target, order.howToCall, calldata, { from: seller }, c);
})];
}
});
});
}
/**
* Delay using setTimeout
* @param ms milliseconds to wait
*/
function delay(ms) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (res) { return setTimeout(res, ms); })];
});
});
}
exports.delay = delay;
/**
* Validates that an address exists, isn't null, and is properly
* formatted for Wyvern and OpenSea
* @param address input address
*/
function validateAndFormatWalletAddress(web3, address) {
if (!address) {
throw new Error('No wallet address found');
}
if (!web3.isAddress(address)) {
throw new Error('Invalid wallet address');
}
if (address == constants_1.NULL_ADDRESS) {
throw new Error('Wallet cannot be the null address');
}
return address.toLowerCase();
}
exports.validateAndFormatWalletAddress = validateAndFormatWalletAddress;
/**
* Notify developer when a pattern will be deprecated
* @param msg message to log to console
*/
function onDeprecated(msg) {
console.warn("DEPRECATION NOTICE: " + msg);
}
exports.onDeprecated = onDeprecated;
/**
* Get special-case approval addresses for an erc721 contract
* @param erc721Contract contract to check
*/
function getNonCompliantApprovalAddress(erc721Contract, tokenId, accountAddress) {
return __awaiter(this, void 0, void 0, function () {
var results;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.all([
// CRYPTOKITTIES check
promisifyCall(function (c) { return erc721Contract.kittyIndexToApproved.call(tokenId, c); }),
// Etherbots check
promisifyCall(function (c) { return erc721Contract.partIndexToApproved.call(tokenId, c); }),
])];
case 1:
results = _a.sent();
return [2 /*return*/, _.compact(results)[0]];
}
});
});
}
exports.getNonCompliantApprovalAddress = getNonCompliantApprovalAddress;
//# sourceMappingURL=utils.js.map