@georgeroman/wyvern-v2-sdk
Version:
Wyvern V2 SDK
235 lines • 8.81 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const abi_1 = require("@ethersproject/abi");
const bytes_1 = require("@ethersproject/bytes");
const contracts_1 = require("@ethersproject/contracts");
const hash_1 = require("@ethersproject/hash");
const solidity_1 = require("@ethersproject/solidity");
const wallet_1 = require("@ethersproject/wallet");
const Erc20_json_1 = __importDefault(require("../abis/Erc20.json"));
const Erc721_json_1 = __importDefault(require("../abis/Erc721.json"));
const Erc1155_json_1 = __importDefault(require("../abis/Erc1155.json"));
const ProxyRegistry_json_1 = __importDefault(require("../abis/ProxyRegistry.json"));
const types_1 = require("../types");
const utils_1 = require("../utils");
const address_1 = __importDefault(require("../utils/address"));
const __1 = require("..");
const WYVERN_ORDER_FIELDS = [
"address",
"address",
"address",
"uint",
"uint",
"uint",
"uint",
"address",
"uint8",
"uint8",
"uint8",
"address",
"uint8",
"bytes",
"bytes",
"address",
"bytes",
"address",
"uint",
"uint",
"uint",
"uint",
"uint", // salt
];
const SIGNATURE_FIELDS = [
"uint8",
"bytes32",
"bytes32", // s
];
class OrderHelper {
static async isApproved(provider, order) {
try {
const chainId = (await provider.getNetwork()).chainId;
if (order.side === types_1.Side.BUY) {
const paymentToken = new contracts_1.Contract(order.paymentToken, new abi_1.Interface(Erc20_json_1.default));
const allowance = await paymentToken
.connect(provider)
.allowance(order.maker, address_1.default.tokenTransferProxy(chainId));
return (0, utils_1.bn)(allowance).gte((0, utils_1.bn)(order.basePrice));
}
else {
const proxyRegistry = new contracts_1.Contract(address_1.default.proxyRegistry(chainId), new abi_1.Interface(ProxyRegistry_json_1.default));
const proxy = await proxyRegistry
.connect(provider)
.proxies(order.maker);
if (!proxy) {
return false;
}
if (__1.Builders.Erc721.SingleItem.isWellFormatted(order)) {
const token = new contracts_1.Contract(order.target, new abi_1.Interface(Erc721_json_1.default));
const isApprovedForAll = await token
.connect(provider)
.isApprovedForAll(order.maker, proxy);
if (!isApprovedForAll) {
const tokenId = __1.Builders.Erc721.SingleItem.extractTokenId(order);
const approved = await token.connect(provider).getApproved(tokenId);
return approved && approved.toLowerCase() === proxy.toLowerCase();
}
return isApprovedForAll;
}
else if (__1.Builders.Erc1155.SingleItem.isWellFormatted(order)) {
const token = new contracts_1.Contract(order.target, new abi_1.Interface(Erc1155_json_1.default));
return token.connect(provider).isApprovedForAll(order.maker, proxy);
}
else {
return false;
}
}
}
catch {
return false;
}
}
static normalize(order) {
// - convert all BigNumbers to string
// - lowercase all strings
return {
exchange: order.exchange.toLowerCase(),
maker: order.maker.toLowerCase(),
taker: order.taker.toLowerCase(),
makerRelayerFee: order.makerRelayerFee.toString(),
takerRelayerFee: order.takerRelayerFee.toString(),
feeRecipient: order.feeRecipient.toLowerCase(),
side: order.side,
saleKind: order.saleKind,
target: order.target.toLowerCase(),
howToCall: order.howToCall,
calldata: order.calldata.toLowerCase(),
replacementPattern: order.replacementPattern.toLowerCase(),
staticTarget: order.staticTarget.toLowerCase(),
staticExtradata: order.staticExtradata.toLowerCase(),
paymentToken: order.paymentToken.toLowerCase(),
basePrice: order.basePrice.toString(),
extra: order.extra.toString(),
listingTime: order.listingTime.toString(),
expirationTime: order.expirationTime.toString(),
salt: order.salt.toString(),
v: order.v,
r: order.r.toLowerCase(),
s: order.s.toLowerCase(),
};
}
static rawHash(order) {
// Return the raw order hash
return (0, solidity_1.keccak256)(WYVERN_ORDER_FIELDS, this.toRaw(order));
}
static hash(order) {
// Return the EIP191 prefix hash
return (0, hash_1.hashMessage)((0, bytes_1.arrayify)(this.rawHash(order)));
}
static encode(order) {
// Skip `makerProtocolFee`, `takerProtocolFee` and `feeMethod` since
// these will always have the same value regardless of the order
return abi_1.defaultAbiCoder.encode([
...WYVERN_ORDER_FIELDS.filter((_, index) => ![5, 6, 8].includes(index)),
...SIGNATURE_FIELDS,
], [
...this.toRaw(order).filter((_, index) => ![5, 6, 8].includes(index)),
order.v,
order.r,
order.s,
]);
}
static decode(order) {
try {
const result = abi_1.defaultAbiCoder.decode([
...WYVERN_ORDER_FIELDS.filter((_, index) => ![5, 6, 8].includes(index)),
...SIGNATURE_FIELDS,
], order);
return this.normalize({
exchange: result[0],
maker: result[1],
taker: result[2],
makerRelayerFee: result[3],
takerRelayerFee: result[4],
feeRecipient: result[5],
side: result[6],
saleKind: result[7],
target: result[8],
howToCall: result[9],
calldata: result[10],
replacementPattern: result[11],
staticTarget: result[12],
staticExtradata: result[13],
paymentToken: result[14],
basePrice: result[15],
extra: result[16],
listingTime: result[17],
expirationTime: result[18],
salt: result[19],
v: result[20],
r: result[21],
s: result[22],
});
}
catch {
return undefined;
}
}
static async sign(signer, order) {
const rawWyvernOrderHash = (0, solidity_1.keccak256)(WYVERN_ORDER_FIELDS, this.toRaw(order));
// Sign the order hash and populate the signature fields
await signer
.signMessage((0, bytes_1.arrayify)(rawWyvernOrderHash))
.then(bytes_1.splitSignature)
.then(({ v, r, s }) => {
order = { ...order, v, r, s };
});
return order;
}
static verifySignature(order) {
const rawWyvernOrderHash = (0, solidity_1.keccak256)(WYVERN_ORDER_FIELDS, this.toRaw(order));
try {
const signerAddress = (0, wallet_1.verifyMessage)((0, bytes_1.arrayify)(rawWyvernOrderHash), {
v: order.v,
r: order.r,
s: order.s,
});
return signerAddress.toLowerCase() === order.maker.toLowerCase();
}
catch {
return false;
}
}
static toRaw(order) {
// Construct raw order including all fields needed by Wyvern
return [
order.exchange,
order.maker,
order.taker,
order.makerRelayerFee,
order.takerRelayerFee,
0,
0,
order.feeRecipient,
1,
order.side,
order.saleKind,
order.target,
order.howToCall,
order.calldata,
order.replacementPattern,
order.staticTarget,
order.staticExtradata,
order.paymentToken,
order.basePrice,
order.extra,
order.listingTime,
order.expirationTime,
order.salt,
];
}
}
exports.default = OrderHelper;
//# sourceMappingURL=order.js.map