UNPKG

hyperspace-sdk

Version:

An unofficial SDK for Hyperspace NFT Marketplace on Avalanche

141 lines (140 loc) 6.33 kB
"use strict"; 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;