hyperspace-sdk
Version:
An unofficial SDK for Hyperspace NFT Marketplace on Avalanche
141 lines (140 loc) • 6.33 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.signOrder = exports.prepareEncodedTransaction = exports.signOrderData = exports.generateRandomV4OrderNonce = exports.generateRandom128BitNumber = exports.verifyAppIdOrThrow = exports.parseRawSignature = void 0;
const bytes_1 = require("@ethersproject/bytes");
const trader_constants_1 = require("./trader_constants");
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
const padStart_1 = __importDefault(require("lodash/padStart"));
const padEnd_1 = __importDefault(require("lodash/padEnd"));
const uuid_1 = require("uuid");
const parseRawSignature = (rawSignature) => {
const hexSize = (0, bytes_1.hexDataLength)(rawSignature);
// if (hexUtils.size(rpcSig) !== 65) {
// throw new Error(`Invalid RPC signature length: "${rpcSig}"`);
// }
if (hexSize !== 65) {
throw new Error(`Invalid signature length, expected 65, got ${hexSize}.\n"Raw signature: ${rawSignature}"`);
}
// Some providers encode V as 0,1 instead of 27,28.
const VALID_V_VALUES = [0, 1, 27, 28];
// Some providers return the signature packed as V,R,S and others R,S,V.
// Try to guess which encoding it is (with a slight preference for R,S,V).
// let v = parseInt(rpcSig.slice(-2), 16);
let v = parseInt(rawSignature.slice(-2), 16);
if (VALID_V_VALUES.includes(v)) {
// Format is R,S,V
v = v >= 27 ? v : v + 27;
return {
// r: hexDataSlice.slice(rpcSig, 0, 32),
// s: hexUtils.slice(rpcSig, 32, 64),
r: (0, bytes_1.hexDataSlice)(rawSignature, 0, 32),
s: (0, bytes_1.hexDataSlice)(rawSignature, 32, 64),
v,
};
}
// Format should be V,R,S
// v = parseInt(rpcSig.slice(2, 4), 16);
v = parseInt(rawSignature.slice(2, 4), 16);
if (!VALID_V_VALUES.includes(v)) {
throw new Error(`Cannot determine RPC signature layout from V value: "${rawSignature}"`);
}
v = v >= 27 ? v : v + 27;
return {
v,
r: (0, bytes_1.hexDataSlice)(rawSignature, 1, 33),
s: (0, bytes_1.hexDataSlice)(rawSignature, 33, 65),
};
};
exports.parseRawSignature = parseRawSignature;
const checkIfStringContainsOnlyNumbers = (val) => {
const onlyNumbers = /^\d+$/.test(val);
return onlyNumbers;
};
const verifyAppIdOrThrow = (appId) => {
const isCorrectLength = appId.length <= trader_constants_1.ONE_TWENTY_EIGHT_BIT_LENGTH - trader_constants_1.RESERVED_APP_ID_PREFIX_DIGITS;
const hasOnlyNumbers = checkIfStringContainsOnlyNumbers(appId);
(0, tiny_invariant_1.default)(isCorrectLength, "appId must be 39 digits or less");
(0, tiny_invariant_1.default)(hasOnlyNumbers, "appId must be numeric only (no alpha or special characters, only numbers)");
};
exports.verifyAppIdOrThrow = verifyAppIdOrThrow;
// uuids are 128bits
const generateRandom128BitNumber = (base = 10) => {
const hex = "0x" + (0, uuid_1.v4)().replace(/-/g, "");
const value = BigInt(hex);
const valueBase10String = value.toString(base); // don't convert this to a number, will lose precision
return valueBase10String;
};
exports.generateRandom128BitNumber = generateRandom128BitNumber;
const generateRandomV4OrderNonce = (appId = "314159") => {
if (appId) {
(0, exports.verifyAppIdOrThrow)(appId);
}
const order128 = (0, padStart_1.default)((0, exports.generateRandom128BitNumber)(), trader_constants_1.ONE_TWENTY_EIGHT_BIT_LENGTH, "0");
const appId128 = (0, padEnd_1.default)(`${trader_constants_1.RESERVED_APP_ID_PREFIX}${appId}`, trader_constants_1.ONE_TWENTY_EIGHT_BIT_LENGTH, "0");
const final256BitNonce = `${appId128}${order128}`;
(0, tiny_invariant_1.default)(final256BitNonce.length <= trader_constants_1.TWO_FIFTY_SIX_BIT_LENGTH, "Invalid nonce size");
return final256BitNonce;
};
exports.generateRandomV4OrderNonce = generateRandomV4OrderNonce;
const signOrderData = async (order, signer) => {
const domain = {
chainId: 43114,
verifyingContract: "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
name: "ZeroEx",
version: "1.0.0",
};
const types = {
[trader_constants_1.ERC721ORDER_STRUCT_NAME]: trader_constants_1.ERC721ORDER_STRUCT_ABI,
Fee: trader_constants_1.FEE_ABI,
Property: trader_constants_1.PROPERTY_ABI,
};
const value = order;
const rawSignatureFromEoaWallet = await signer._signTypedData(domain, types, value);
return rawSignatureFromEoaWallet;
};
exports.signOrderData = signOrderData;
const prepareEncodedTransaction = async (signer, gasPriceMultiplier, gasLimitMultiplier, transactionInput) => {
const signerAddress = await signer.getAddress();
const signerNonce = await signer.provider.getTransactionCount(signerAddress);
let constructedTransaction = {
chainId: 43114,
nonce: signerNonce,
to: "0x398BAa6FFc99126671Ab6be565856105a6118A40",
data: "0x",
value: "0x0",
gasPrice: "0",
gasLimit: "0",
};
if (transactionInput.data) {
constructedTransaction.data = transactionInput.data;
}
if (transactionInput.value) {
constructedTransaction.value = transactionInput.value;
}
const gasPrice = await signer.provider.getGasPrice();
const gasEstimate = await signer.estimateGas(constructedTransaction);
// Double the gas price and limit to be safe.
constructedTransaction.gasPrice = gasPrice.mul(gasPriceMultiplier)._hex;
constructedTransaction.gasLimit = gasEstimate.mul(gasLimitMultiplier)._hex;
return constructedTransaction;
};
exports.prepareEncodedTransaction = prepareEncodedTransaction;
const signOrder = async (order, signer) => {
const rawSignature = await (0, exports.signOrderData)(order, signer);
const ecSignature = (0, exports.parseRawSignature)(rawSignature);
const signedOrder = {
...order,
signature: {
signatureType: 2,
r: ecSignature.r,
s: ecSignature.s,
v: ecSignature.v,
},
rawSignature,
};
return signedOrder;
};
exports.signOrder = signOrder;