diff --git a/.vscode/settings.json b/.vscode/settings.json index 3daa486b..7235ee70 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,7 +14,7 @@ { "pattern": "tooling/*/" } ], "eslint.runtime": "node", - "tailwindCSS.experimental.configFile": "./tooling/tailwind/index.ts", + "tailwindCSS.experimental.configFile": "./tooling/tailwind/web.ts", "typescript.enablePromptUseWorkspaceTsdk": true, "typescript.tsdk": "node_modules/typescript/lib", "typescript.preferences.autoImportFileExcludePatterns": [ @@ -24,12 +24,7 @@ "deno.enable": false, "deno.lint": false, "deno.unstable": false, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[typescriptreact]": { - // Sometimes vscode prettier doesn't format .tsx file without this config. - // see also: https://stackoverflow.com/questions/61731587/vscode-prettier-doesnt-format-tsx-file + "[typescript,typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" } diff --git a/apps/frontinus-house/package.json b/apps/frontinus-house/package.json index a5ef5316..b1325c93 100644 --- a/apps/frontinus-house/package.json +++ b/apps/frontinus-house/package.json @@ -26,7 +26,7 @@ "react-router-dom": "^6.24.0", "remarkable": "^2.0.1", "starknet": "5.25.0", - "tailwindcss": "3.4.10" + "tailwindcss": "catalog:" }, "devDependencies": { "@types/node": "^22.3.0", diff --git a/apps/frontinus-house/src/components/Markdown.jsx b/apps/frontinus-house/src/components/Markdown.jsx new file mode 100644 index 00000000..8802cb89 --- /dev/null +++ b/apps/frontinus-house/src/components/Markdown.jsx @@ -0,0 +1,109 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Markdown = Markdown; +var react_1 = require("react"); +var utils_1 = require("@/lib/utils"); +var heroicons_outline_1 = require("@iconify-json/heroicons-outline"); +var core_1 = require("highlight.js/lib/core"); +var javascript_1 = require("highlight.js/lib/languages/javascript"); +var json_1 = require("highlight.js/lib/languages/json"); +var python_1 = require("highlight.js/lib/languages/python"); +var rust_1 = require("highlight.js/lib/languages/rust"); +var highlightjs_solidity_1 = require("highlightjs-solidity"); +var remarkable_1 = require("remarkable"); +var linkify_1 = require("remarkable/linkify"); +core_1.default.registerLanguage("javascript", javascript_1.default); +core_1.default.registerLanguage("json", json_1.default); +core_1.default.registerLanguage("rust", rust_1.default); +core_1.default.registerLanguage("python", python_1.default); +core_1.default.registerLanguage("solidity", highlightjs_solidity_1.solidity); +function Markdown(_a) { + //const { copy } = useClipboard(); + var body = _a.body; + var remarkable = new remarkable_1.Remarkable({ + html: false, + breaks: true, + typographer: false, + linkTarget: "_blank", + highlight: function (str, lang) { + if (lang && core_1.default.getLanguage(lang)) { + try { + return core_1.default.highlight(str, { language: lang }).value; + } + catch (e) { } + } + try { + return core_1.default.highlightAuto(str).value; + } + catch (e) { } + return ""; + }, + }).use(linkify_1.linkify); + remarkable.core.ruler.disable([ + "abbr", + "abbr2", + "footnote_tail", + "replacements", + "smartquotes", + ]); + remarkable.block.ruler.disable([ + "code", + "deflist", + "footnote", + "htmlblock", + "lheading", + ]); + remarkable.inline.ruler.disable([ + "autolink", + "del", + "entity", + "escape", + "footnote_inline", + "footnote_ref", + "htmltag", + "ins", + "mark", + "sub", + "sup", + "text", + ]); + var parsed = function () { + var formattedBody = body.replace(/ipfs:\/\/(\w+)/g, function (value) { return (0, utils_1.getUrl)(value) || "#"; }); + return remarkable.render(formattedBody); + }; + (0, react_1.useEffect)(function () { + var body = document.querySelector(".markdown-body"); + if (!body) + return; + body.querySelectorAll("pre>code").forEach(function (code) { + var _a, _b; + var parent = code.parentElement; + var copyButton = document.createElement("button"); + var copySvg = "".concat((_a = heroicons_outline_1.icons.icons.duplicate) === null || _a === void 0 ? void 0 : _a.body, ""); + copyButton.classList.add("text-skin-text"); + copyButton.setAttribute("type", "button"); + copyButton.innerHTML = copySvg; + copyButton.addEventListener("click", function () { + var _a; + if (parent !== null) { + //copy(code.textContent!); + copyButton.innerHTML = "".concat((_a = heroicons_outline_1.icons.icons.check) === null || _a === void 0 ? void 0 : _a.body, ""); + copyButton.classList.add("!text-skin-success"); + setTimeout(function () { + copyButton.innerHTML = copySvg; + copyButton.classList.remove("!text-skin-success"); + }, 1e3); + } + }); + var titleBar = document.createElement("div"); + titleBar.classList.add("title-bar"); + var language = document.createElement("div"); + language.innerHTML = + ((_b = code.getAttribute("class")) === null || _b === void 0 ? void 0 : _b.split("language-")[1]) || ""; + titleBar.append(language); + titleBar.append(copyButton); + parent.prepend(titleBar); + }); + }); + return (
); +} diff --git a/apps/frontinus-house/src/components/app-shell.jsx b/apps/frontinus-house/src/components/app-shell.jsx new file mode 100644 index 00000000..baefde84 --- /dev/null +++ b/apps/frontinus-house/src/components/app-shell.jsx @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = AppShell; +var sidebar_1 = require("@/components/sidebar"); +var use_is_collapsed_1 = require("@/hooks/use-is-collapsed"); +var react_router_dom_1 = require("react-router-dom"); +var header_1 = require("./header"); +function AppShell() { + var _a = (0, use_is_collapsed_1.default)(), isCollapsed = _a[0], setIsCollapsed = _a[1]; + return (
+ +
+ +
+ +
+
+
); +} diff --git a/apps/frontinus-house/src/components/header.jsx b/apps/frontinus-house/src/components/header.jsx new file mode 100644 index 00000000..7d5dea21 --- /dev/null +++ b/apps/frontinus-house/src/components/header.jsx @@ -0,0 +1,76 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Header; +var menuLinks_1 = require("@/data/menuLinks"); +var lucide_react_1 = require("lucide-react"); +var react_router_dom_1 = require("react-router-dom"); +var button_1 = require("@realms-world/ui/components/ui/button"); +var card_1 = require("@realms-world/ui/components/ui/card"); +var dropdown_menu_1 = require("@realms-world/ui/components/ui/dropdown-menu"); +var input_1 = require("@realms-world/ui/components/ui/input"); +var sheet_1 = require("@realms-world/ui/components/ui/sheet"); +function Header() { + return (
+ + + + + Toggle navigation menu + + + + +
+ + + Upgrade to Pro + + Unlock all features and get unlimited access to our support + team. + + + + + Upgrade + + + +
+
+
+
+
+
+ + +
+
+
+ + + + + Toggle user menu + + + + My Account + + Settings + Support + + Logout + + +
); +} diff --git a/apps/frontinus-house/src/components/layout.jsx b/apps/frontinus-house/src/components/layout.jsx new file mode 100644 index 00000000..2350b2b2 --- /dev/null +++ b/apps/frontinus-house/src/components/layout.jsx @@ -0,0 +1,35 @@ +"use strict"; +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LayoutBody = exports.LayoutHeader = exports.Layout = void 0; +var React = require("react"); +var utils_1 = require("@realms-world/utils"); +var Layout = React.forwardRef(function (_a, ref) { + var className = _a.className, _b = _a.fadedBelow, fadedBelow = _b === void 0 ? false : _b, _c = _a.fixedHeight, fixedHeight = _c === void 0 ? false : _c, props = __rest(_a, ["className", "fadedBelow", "fixedHeight"]); + return (
); +}); +exports.Layout = Layout; +Layout.displayName = 'Layout'; +var LayoutHeader = React.forwardRef(function (_a, ref) { + var className = _a.className, props = __rest(_a, ["className"]); + return (
); +}); +exports.LayoutHeader = LayoutHeader; +LayoutHeader.displayName = 'LayoutHeader'; +var LayoutBody = React.forwardRef(function (_a, ref) { + var className = _a.className, fixedHeight = _a.fixedHeight, props = __rest(_a, ["className", "fixedHeight"]); + return (
); +}); +exports.LayoutBody = LayoutBody; +LayoutBody.displayName = 'LayoutBody'; diff --git a/apps/frontinus-house/src/components/sidebar.jsx b/apps/frontinus-house/src/components/sidebar.jsx new file mode 100644 index 00000000..4a797085 --- /dev/null +++ b/apps/frontinus-house/src/components/sidebar.jsx @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Sidebar; +var menuLinks_1 = require("@/data/menuLinks"); +var lucide_react_1 = require("lucide-react"); +var react_router_dom_1 = require("react-router-dom"); +var button_1 = require("@realms-world/ui/components/ui/button"); +var card_1 = require("@realms-world/ui/components/ui/card"); +function Sidebar(_a) { + var className = _a.className, isCollapsed = _a.isCollapsed, setIsCollapsed = _a.setIsCollapsed; + return (
+
+
+ + + Frontinus House + + + + Toggle notifications + +
+
+ +
+
+ + + Want To Govern? + + Purchase a Realm NFT to particpate in the governance of the Realms Autonomous World + + + + + Realms.World + + + +
+
+
); +} diff --git a/apps/frontinus-house/src/components/space-provider.jsx b/apps/frontinus-house/src/components/space-provider.jsx new file mode 100644 index 00000000..08f24434 --- /dev/null +++ b/apps/frontinus-house/src/components/space-provider.jsx @@ -0,0 +1,85 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.useSpace = void 0; +exports.SpaceProvider = SpaceProvider; +var react_1 = require("react"); +var network_1 = require("@/lib/network"); +var initialState = { + space: null, + setSpace: function () { return null; }, +}; +var SpaceProviderContext = (0, react_1.createContext)(initialState); +//Should probably be replaced by Apollo React client +function SpaceProvider(_a) { + var _this = this; + var children = _a.children; + var _b = (0, react_1.useState)(), space = _b[0], setSpace = _b[1]; + (0, react_1.useEffect)(function () { + var fetchProposals = function () { return __awaiter(_this, void 0, void 0, function () { + var spaceData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, network_1.getNetwork)("sn-sep").api.loadSpace("0x0011c8d7674bb371708933d29c5e2a4ea31a6535809950b863851373f1afc112")]; + case 1: + spaceData = _a.sent(); + spaceData && setSpace(spaceData); + return [2 /*return*/]; + } + }); + }); }; + fetchProposals(); + }, []); + var value = { + space: space, + setSpace: function (space) { + setSpace(space); + }, + }; + return ( + {children} + ); +} +// eslint-disable-next-line react-refresh/only-export-components +var useSpace = function () { + var context = (0, react_1.useContext)(SpaceProviderContext); + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider"); + return context; +}; +exports.useSpace = useSpace; diff --git a/apps/frontinus-house/src/data/constants.js b/apps/frontinus-house/src/data/constants.js new file mode 100644 index 00000000..b9c04e31 --- /dev/null +++ b/apps/frontinus-house/src/data/constants.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SUPPORTED_VOTING_TYPES = exports.BASIC_CHOICES = exports.MAX_SYMBOL_LENGTH = exports.COINGECKO_BASE_ASSETS = exports.COINGECKO_ASSET_PLATFORMS = exports.CHAIN_IDS = exports.ETH_CONTRACT = void 0; +exports.ETH_CONTRACT = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'; +exports.CHAIN_IDS = { + matic: 137, + arb1: 42161, + oeth: 10, + eth: 1, + gor: 5, + sep: 11155111, + 'linea-testnet': 59140 +}; +exports.COINGECKO_ASSET_PLATFORMS = { + 1: 'ethereum', + 10: 'optimistic-ethereum', + 137: 'polygon-pos', + 42161: 'arbitrum-one' +}; +exports.COINGECKO_BASE_ASSETS = { + 1: 'ethereum', + 10: 'ethereum', + 137: 'matic-network', + 42161: 'ethereum' +}; +exports.MAX_SYMBOL_LENGTH = 12; +exports.BASIC_CHOICES = ['For', 'Against', 'Abstain']; +exports.SUPPORTED_VOTING_TYPES = [ + 'basic', + 'single-choice', + 'approval', + 'ranked-choice', + 'weighted', + 'quadratic' +]; diff --git a/apps/frontinus-house/src/data/menuLinks.jsx b/apps/frontinus-house/src/data/menuLinks.jsx new file mode 100644 index 00000000..84c52c35 --- /dev/null +++ b/apps/frontinus-house/src/data/menuLinks.jsx @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sidelinks = void 0; +var lucide_react_1 = require("lucide-react"); +exports.sidelinks = [ + { + title: "Overview", + label: "", + href: "/", + icon: , + }, + { + title: "Proposals", + label: "3", + href: "/proposals", + icon: , + }, + { + title: "Rounds", + label: "9", + href: "/rounds", + icon: , + }, + { + title: "Delegates", + label: "", + href: "/delegates", + icon: , + }, +]; diff --git a/apps/frontinus-house/src/hooks/use-delegates.jsx b/apps/frontinus-house/src/hooks/use-delegates.jsx new file mode 100644 index 00000000..ada2adad --- /dev/null +++ b/apps/frontinus-house/src/hooks/use-delegates.jsx @@ -0,0 +1,208 @@ +"use strict"; +var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.useDelegates = useDelegates; +var react_1 = require("react"); +var stamp_1 = require("@/lib/stamp"); +var core_1 = require("@apollo/client/core"); +var graphql_tag_1 = require("graphql-tag"); +var DELEGATES_LIMIT = 40; +var DELEGATES_QUERY = (0, graphql_tag_1.default)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n query (\n $first: Int!\n $skip: Int!\n $orderBy: Delegate_orderBy!\n $orderDirection: OrderDirection!\n ) {\n delegates(\n first: $first\n skip: $skip\n orderBy: $orderBy\n orderDirection: $orderDirection\n where: { tokenHoldersRepresentedAmount_gte: 0 }\n ) {\n id\n delegatedVotes\n delegatedVotesRaw\n tokenHoldersRepresentedAmount\n }\n governance(id: \"GOVERNANCE\") {\n delegatedVotes\n totalTokenHolders\n totalDelegates\n }\n }\n"], ["\n query (\n $first: Int!\n $skip: Int!\n $orderBy: Delegate_orderBy!\n $orderDirection: OrderDirection!\n ) {\n delegates(\n first: $first\n skip: $skip\n orderBy: $orderBy\n orderDirection: $orderDirection\n where: { tokenHoldersRepresentedAmount_gte: 0 }\n ) {\n id\n delegatedVotes\n delegatedVotesRaw\n tokenHoldersRepresentedAmount\n }\n governance(id: \"GOVERNANCE\") {\n delegatedVotes\n totalTokenHolders\n totalDelegates\n }\n }\n"]))); +function convertUrl(apiUrl) { + var hostedPattern = /https:\/\/thegraph\.com\/hosted-service\/subgraph\/([\w-]+)\/([\w-]+)/; + var hostedMatch = apiUrl.match(hostedPattern); + if (hostedMatch) { + return "https://api.thegraph.com/subgraphs/name/".concat(hostedMatch[1], "/").concat(hostedMatch[2]); + } + return apiUrl; +} +function useDelegates(delegationApiUrl) { + var _a = (0, react_1.useState)([]), delegates = _a[0], setDelegates = _a[1]; + var _b = (0, react_1.useState)(false), loading = _b[0], setLoading = _b[1]; + var _c = (0, react_1.useState)(false), loadingMore = _c[0], setLoadingMore = _c[1]; + var _d = (0, react_1.useState)(false), loaded = _d[0], setLoaded = _d[1]; + var _e = (0, react_1.useState)(false), failed = _e[0], setFailed = _e[1]; + var _f = (0, react_1.useState)(false), hasMore = _f[0], setHasMore = _f[1]; + var httpLink = (0, core_1.createHttpLink)({ + uri: convertUrl(delegationApiUrl), + }); + var apollo = new core_1.ApolloClient({ + link: httpLink, + cache: new core_1.InMemoryCache({ + addTypename: false, + }), + defaultOptions: { + query: { + fetchPolicy: "no-cache", + }, + }, + }); + function _fetch(overwrite, sortBy) { + return __awaiter(this, void 0, void 0, function () { + var _a, orderBy, orderDirection, data, governanceData, delegatesData, addresses, names, newDelegates; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = sortBy.split("-"), orderBy = _a[0], orderDirection = _a[1]; + return [4 /*yield*/, apollo.query({ + query: DELEGATES_QUERY, + variables: { + orderBy: orderBy, + orderDirection: orderDirection, + first: DELEGATES_LIMIT, + skip: overwrite ? 0 : delegates.length, + }, + })]; + case 1: + data = (_b.sent()).data; + console.log(data); + governanceData = data.governance; + delegatesData = data.delegates; + addresses = delegatesData.map(function (delegate) { return delegate.id; }); + return [4 /*yield*/, (0, stamp_1.getNames)(addresses)]; + case 2: + names = _b.sent(); + newDelegates = delegatesData.map(function (delegate) { + var delegatorsPercentage = (Number(delegate.tokenHoldersRepresentedAmount) / + Number(governanceData.totalTokenHolders)) * + 100; + var votesPercentage = (Number(delegate.delegatedVotes) / + Number(governanceData.delegatedVotes)) * + 100 || 0; + return __assign(__assign({ name: names[delegate.id] || null }, delegate), { delegatorsPercentage: delegatorsPercentage, votesPercentage: votesPercentage }); + }); + setDelegates(overwrite ? newDelegates : __spreadArray(__spreadArray([], delegates, true), newDelegates, true)); + setHasMore(delegatesData.length === DELEGATES_LIMIT); + return [2 /*return*/]; + } + }); + }); + } + function fetch() { + return __awaiter(this, arguments, void 0, function (sortBy) { + var e_1; + if (sortBy === void 0) { sortBy = "delegatedVotes-desc"; } + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (loading || loaded) + return [2 /*return*/]; + setLoading(true); + _a.label = 1; + case 1: + _a.trys.push([1, 3, 4, 5]); + return [4 /*yield*/, _fetch(true, sortBy)]; + case 2: + _a.sent(); + setLoaded(true); + return [3 /*break*/, 5]; + case 3: + e_1 = _a.sent(); + setFailed(true); + return [3 /*break*/, 5]; + case 4: + setLoading(false); + return [7 /*endfinally*/]; + case 5: return [2 /*return*/]; + } + }); + }); + } + function fetchMore() { + return __awaiter(this, arguments, void 0, function (sortBy) { + if (sortBy === void 0) { sortBy = "delegatedVotes-desc"; } + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (loading || !loaded) + return [2 /*return*/]; + setLoadingMore(true); + return [4 /*yield*/, _fetch(false, sortBy)]; + case 1: + _a.sent(); + setLoadingMore(false); + return [2 /*return*/]; + } + }); + }); + } + function reset() { + setDelegates([]); + setLoading(false); + setLoadingMore(false); + setLoaded(false); + setFailed(false); + setHasMore(false); + } + return { + loading: loading, + loadingMore: loadingMore, + loaded: loaded, + failed: failed, + hasMore: hasMore, + delegates: delegates, + fetch: fetch, + fetchMore: fetchMore, + reset: reset, + }; +} +var templateObject_1; diff --git a/apps/frontinus-house/src/hooks/use-is-collapsed.jsx b/apps/frontinus-house/src/hooks/use-is-collapsed.jsx new file mode 100644 index 00000000..e401c389 --- /dev/null +++ b/apps/frontinus-house/src/hooks/use-is-collapsed.jsx @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = useIsCollapsed; +var react_1 = require("react"); +var use_local_storage_1 = require("@/hooks/use-local-storage"); +function useIsCollapsed() { + var _a = (0, use_local_storage_1.default)({ + key: 'collapsed-sidebar', + defaultValue: false, + }), isCollapsed = _a[0], setIsCollapsed = _a[1]; + (0, react_1.useEffect)(function () { + var handleResize = function () { + // Update isCollapsed based on window.innerWidth + setIsCollapsed(window.innerWidth < 768 ? false : isCollapsed); + }; + // Initial setup + handleResize(); + // Add event listener for window resize + window.addEventListener('resize', handleResize); + // Cleanup event listener on component unmount + return function () { + window.removeEventListener('resize', handleResize); + }; + }, [isCollapsed, setIsCollapsed]); + return [isCollapsed, setIsCollapsed]; +} diff --git a/apps/frontinus-house/src/hooks/use-local-storage.jsx b/apps/frontinus-house/src/hooks/use-local-storage.jsx new file mode 100644 index 00000000..5739e9d8 --- /dev/null +++ b/apps/frontinus-house/src/hooks/use-local-storage.jsx @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = useLocalStorage; +var react_1 = require("react"); +function useLocalStorage(_a) { + var key = _a.key, defaultValue = _a.defaultValue; + var _b = (0, react_1.useState)(function () { + var storedValue = localStorage.getItem(key); + return storedValue !== null ? JSON.parse(storedValue) : defaultValue; + }), value = _b[0], setValue = _b[1]; + (0, react_1.useEffect)(function () { + localStorage.setItem(key, JSON.stringify(value)); + }, [value, key]); + return [value, setValue]; +} diff --git a/apps/frontinus-house/src/lib/alchemy/index.js b/apps/frontinus-house/src/lib/alchemy/index.js new file mode 100644 index 00000000..148d226d --- /dev/null +++ b/apps/frontinus-house/src/lib/alchemy/index.js @@ -0,0 +1,225 @@ +"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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.request = request; +exports.batchRequest = batchRequest; +exports.getBalance = getBalance; +exports.getTokenBalances = getTokenBalances; +exports.getTokensMetadata = getTokensMetadata; +exports.getBalances = getBalances; +var constants_1 = require("@/data/constants"); +__exportStar(require("./types"), exports); +var apiKey = import.meta.env.VITE_ALCHEMY_API_KEY; +var NETWORKS = { + 1: "eth-mainnet", + 5: "eth-goerli", + 11155111: "eth-sepolia", + 10: "opt-mainnet", + 137: "polygon-mainnet", + 42161: "arb-mainnet", +}; +function getApiUrl(networkId) { + var _a; + var network = (_a = NETWORKS[networkId]) !== null && _a !== void 0 ? _a : "mainnet"; + return "https://".concat(network, ".g.alchemy.com/v2/").concat(apiKey); +} +function request(method, params, networkId) { + return __awaiter(this, void 0, void 0, function () { + var res, result; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, fetch(getApiUrl(networkId), { + method: "POST", + body: JSON.stringify({ + id: 1, + jsonrpc: "2.0", + method: method, + params: params, + }), + })]; + case 1: + res = _a.sent(); + return [4 /*yield*/, res.json()]; + case 2: + result = (_a.sent()).result; + return [2 /*return*/, result]; + } + }); + }); +} +function batchRequest(requests, networkId) { + return __awaiter(this, void 0, void 0, function () { + var res, response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, fetch(getApiUrl(networkId), { + method: "POST", + body: JSON.stringify(requests.map(function (request, i) { return ({ + id: i, + jsonrpc: "2.0", + method: request.method, + params: request.params, + }); })), + })]; + case 1: + res = _a.sent(); + return [4 /*yield*/, res.json()]; + case 2: + response = _a.sent(); + return [2 /*return*/, response.map(function (entry) { return entry.result; })]; + } + }); + }); +} +/** + * Gets Ethereum balance as hex encoded string. + * @param address Ethereum address to fetch ETH balance for + * @param networkId Network ID + * @returns Hex encoded ETH balance + */ +function getBalance(address, networkId) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, request("eth_getBalance", [address], networkId)]; + }); + }); +} +/** + * Gets ERC20 balances of tokens that provided address interacted with. + * Response might include 0 balances. + * @param address Ethereum address to fetch token balances for + * @param networkId Network ID + * @returns Token balances + */ +function getTokenBalances(address, networkId) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, request("alchemy_getTokenBalances", [address], networkId)]; + }); + }); +} +/** + * Gets ERC20 tokens metadata (name, symbol, decimals, logo). + * @param addresses Array of ERC20 tokens addresses + * @param networkId Network ID + * @returns Array of token metadata + */ +function getTokensMetadata(addresses, networkId) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, batchRequest(addresses.map(function (address) { return ({ + method: "alchemy_getTokenMetadata", + params: [address], + }); }), networkId)]; + }); + }); +} +/** + * Gets Ethereum and ERC20 balances including metadata for tokens. + * @param address Ethereum address to fetch balances for + * @param networkId Network ID + * @returns Array of balances + */ +function getBalances(address, networkId, baseToken) { + return __awaiter(this, void 0, void 0, function () { + var _a, ethBalance, tokenBalances, contractAddresses, metadata; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, Promise.all([ + getBalance(address, networkId), + getTokenBalances(address, networkId), + ])]; + case 1: + _a = _b.sent(), ethBalance = _a[0], tokenBalances = _a[1].tokenBalances; + contractAddresses = tokenBalances.map(function (balance) { return balance.contractAddress; }); + return [4 /*yield*/, getTokensMetadata(contractAddresses, networkId)]; + case 2: + metadata = _b.sent(); + return [2 /*return*/, __spreadArray([ + { + name: baseToken.name, + symbol: baseToken.symbol, + decimals: 18, + logo: null, + contractAddress: constants_1.ETH_CONTRACT, + tokenBalance: ethBalance, + price: 0, + value: 0, + change: 0, + } + ], tokenBalances + .map(function (balance, i) { return (__assign(__assign(__assign({}, balance), metadata[i]), { price: 0, value: 0, change: 0 })); }) + .filter(function (token) { return token.symbol && !token.symbol.includes("."); }), true)]; + } + }); + }); +} diff --git a/apps/frontinus-house/src/lib/alchemy/types.js b/apps/frontinus-house/src/lib/alchemy/types.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/apps/frontinus-house/src/lib/alchemy/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/apps/frontinus-house/src/lib/link.js b/apps/frontinus-house/src/lib/link.js new file mode 100644 index 00000000..d0ff272a --- /dev/null +++ b/apps/frontinus-house/src/lib/link.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getSwapLink = getSwapLink; +var UNISWAP_CHAINS_BY_NETWORK = { + "1": "mainnet", + "42161": "arbitrum", + "10": "optimism", + "137": "polygon", + "8453": "base", + "56": "bnb", + "43114": "avalanche", + "42220": "celo", + "11155111": "sepolia", + "5": "goerli", +}; +function getSwapLink(strategy, address, chainId) { + if (strategy && + address && + chainId && + [ + "comp", + "ozVotes", + "erc20-balance-of", + "erc20-votes", + "comp-like-votes", + "uni", + "erc20-balance-of-with-delegation", + ].includes(strategy)) { + //@ts-expect-error uniswap type network error + var chain = UNISWAP_CHAINS_BY_NETWORK[chainId]; + return "https://app.uniswap.org/swap?inputCurrency=ETH&outputCurrency=".concat(address, "&chain=").concat(chain, "&ref=snapshot"); + } + return; +} diff --git a/apps/frontinus-house/src/lib/mana.js b/apps/frontinus-house/src/lib/mana.js new file mode 100644 index 00000000..b54be2b4 --- /dev/null +++ b/apps/frontinus-house/src/lib/mana.js @@ -0,0 +1,85 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MANA_URL = void 0; +exports.registerTransaction = registerTransaction; +exports.executionCall = executionCall; +exports.MANA_URL = import.meta.env.VITE_MANA_URL || "http://localhost:3000"; +function rpcCall(path, method, params) { + return __awaiter(this, void 0, void 0, function () { + var res, _a, error, result; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, fetch("".concat(exports.MANA_URL, "/").concat(path), { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + method: method, + params: params, + id: null, + }), + })]; + case 1: + res = _b.sent(); + return [4 /*yield*/, res.json()]; + case 2: + _a = _b.sent(), error = _a.error, result = _a.result; + if (error) + throw new Error("RPC call failed"); + return [2 /*return*/, result]; + } + }); + }); +} +function registerTransaction(chainId, params) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, rpcCall("stark_rpc/".concat(chainId), "registerTransaction", params)]; + }); + }); +} +function executionCall(network, chainId, method, params) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, rpcCall("".concat(network, "_rpc/").concat(chainId), method, params)]; + }); + }); +} diff --git a/apps/frontinus-house/src/lib/network/common/constants.js b/apps/frontinus-house/src/lib/network/common/constants.js new file mode 100644 index 00000000..1fb63dc6 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/common/constants.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.STARKNET_CONNECTORS = exports.EVM_CONNECTORS = void 0; +exports.EVM_CONNECTORS = ['injected', 'walletconnect', 'walletlink', 'gnosis']; +exports.STARKNET_CONNECTORS = ['argentx']; diff --git a/apps/frontinus-house/src/lib/network/common/helpers.js b/apps/frontinus-house/src/lib/network/common/helpers.js new file mode 100644 index 00000000..04aa8d45 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/common/helpers.js @@ -0,0 +1,183 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getSdkChoice = getSdkChoice; +exports.getExecutionData = getExecutionData; +exports.parseStrategyMetadata = parseStrategyMetadata; +exports.buildMetadata = buildMetadata; +exports.createStrategyPicker = createStrategyPicker; +var utils_1 = require("@/lib/utils"); +var sx_1 = require("@snapshot-labs/sx"); +//import { MetaTransaction } from '@snapshot-labs/sx/dist/utils/encoding/execution-hash'; +var constants_1 = require("./constants"); +function getSdkChoice(choice) { + if (choice === "for") + return sx_1.Choice.For; + if (choice === "against") + return sx_1.Choice.Against; + return sx_1.Choice.Abstain; +} +function getExecutionData(space, executionStrategy, destinationAddress, transactions) { + var supportedExecutionIndex = space.executors.findIndex(function (executor) { return executor === executionStrategy; }); + if (supportedExecutionIndex === -1) { + throw new Error("No supported executor configured for this space"); + } + var executorType = space.executors_types[supportedExecutionIndex]; + return (0, sx_1.getExecutionData)(executorType, executionStrategy, { + transactions: transactions, + destination: destinationAddress || undefined, + }); +} +function parseStrategyMetadata(metadata) { + return __awaiter(this, void 0, void 0, function () { + var strategyUrl, res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (metadata === null) + return [2 /*return*/, null]; + if (!metadata.startsWith("ipfs://")) + return [2 /*return*/, JSON.parse(metadata)]; + strategyUrl = (0, utils_1.getUrl)(metadata); + if (!strategyUrl) + return [2 /*return*/, null]; + return [4 /*yield*/, fetch(strategyUrl)]; + case 1: + res = _a.sent(); + return [2 /*return*/, res.json()]; + } + }); + }); +} +function buildMetadata(helpers, config) { + return __awaiter(this, void 0, void 0, function () { + var metadata, pinned; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!config.generateMetadata) + return [2 /*return*/, ""]; + return [4 /*yield*/, config.generateMetadata(config.params)]; + case 1: + metadata = _a.sent(); + return [4 /*yield*/, helpers.pin(metadata)]; + case 2: + pinned = _a.sent(); + return [2 /*return*/, "ipfs://".concat(pinned.cid)]; + } + }); + }); +} +function createStrategyPicker(_a) { + var helpers = _a.helpers, managerConnectors = _a.managerConnectors, _b = _a.lowPriorityAuthenticators, lowPriorityAuthenticators = _b === void 0 ? [] : _b; + return function pick(_a) { + var authenticators = _a.authenticators, strategies = _a.strategies, strategiesIndicies = _a.strategiesIndicies, isContract = _a.isContract, connectorType = _a.connectorType; + var authenticatorsInfo = __spreadArray([], authenticators, true).filter(function (authenticator) { + return isContract + ? helpers.isAuthenticatorContractSupported(authenticator) + : helpers.isAuthenticatorSupported(authenticator); + }) + .sort(function (a, b) { + var aRelayer = helpers.getRelayerAuthenticatorType(a); + var bRelayer = helpers.getRelayerAuthenticatorType(b); + var aLowPriority = aRelayer && lowPriorityAuthenticators.includes(aRelayer); + var bLowPriority = bRelayer && lowPriorityAuthenticators.includes(bRelayer); + if (aLowPriority && !bLowPriority) { + return 1; + } + if (!aLowPriority && bLowPriority) { + return -1; + } + if (aRelayer && bRelayer) { + return 0; + } + if (aRelayer) { + return -1; + } + if (bRelayer) { + return 1; + } + return 0; + }) + .map(function (authenticator) { + var relayerType = helpers.getRelayerAuthenticatorType(authenticator); + var connectors = []; + if (relayerType && ["evm", "evm-tx"].includes(relayerType)) + connectors = constants_1.EVM_CONNECTORS; + else if (relayerType === "starknet") + connectors = constants_1.STARKNET_CONNECTORS; + else + connectors = managerConnectors; + return { + authenticator: authenticator, + relayerType: relayerType, + connectors: connectors, + }; + }); + var authenticatorInfo = authenticatorsInfo.find(function (_a) { + var connectors = _a.connectors; + return connectors.includes(connectorType); + }); + var selectedStrategies = strategies + .map(function (strategy, index) { + return ({ address: strategy, index: strategiesIndicies[index] }); + }) + .filter(function (_a) { + var address = _a.address; + return helpers.isStrategySupported(address); + }); + if (!authenticatorInfo || + (strategies.length !== 0 && selectedStrategies.length === 0)) { + throw new Error("Unsupported space"); + } + return { + relayerType: authenticatorInfo.relayerType, + authenticator: authenticatorInfo.authenticator, + strategies: selectedStrategies, + }; + }; +} diff --git a/apps/frontinus-house/src/lib/network/common/highlight.js b/apps/frontinus-house/src/lib/network/common/highlight.js new file mode 100644 index 00000000..7e479485 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/common/highlight.js @@ -0,0 +1,92 @@ +"use strict"; +var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; +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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.USER_QUERY = exports.VOTES_QUERY = exports.PROPOSALS_QUERY = exports.PROPOSAL_QUERY = exports.SPACES_QUERY = exports.SPACE_QUERY = void 0; +exports.joinHighlightSpace = joinHighlightSpace; +exports.joinHighlightProposal = joinHighlightProposal; +exports.joinHighlightUser = joinHighlightUser; +exports.mixinHighlightVotes = mixinHighlightVotes; +var graphql_tag_1 = require("graphql-tag"); +var SPACE_FRAGMENT = (0, graphql_tag_1.default)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n fragment highlightSpaceFragment on SXSpace {\n id\n vote_count\n }\n"], ["\n fragment highlightSpaceFragment on SXSpace {\n id\n vote_count\n }\n"]))); +var PROPOSAL_FRAGMENT = (0, graphql_tag_1.default)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n fragment highlightProposalFragment on SXProposal {\n id\n scores_1\n scores_2\n scores_3\n scores_total\n vote_count\n }\n"], ["\n fragment highlightProposalFragment on SXProposal {\n id\n scores_1\n scores_2\n scores_3\n scores_total\n vote_count\n }\n"]))); +exports.SPACE_QUERY = (0, graphql_tag_1.default)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n query ($id: String!) {\n sxspace(id: $id) {\n ...highlightSpaceFragment\n }\n }\n ", "\n"], ["\n query ($id: String!) {\n sxspace(id: $id) {\n ...highlightSpaceFragment\n }\n }\n ", "\n"])), SPACE_FRAGMENT); +exports.SPACES_QUERY = (0, graphql_tag_1.default)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n query ($ids: [String!]!) {\n sxspaces(where: { id_in: $ids }) {\n ...highlightSpaceFragment\n }\n }\n ", "\n"], ["\n query ($ids: [String!]!) {\n sxspaces(where: { id_in: $ids }) {\n ...highlightSpaceFragment\n }\n }\n ", "\n"])), SPACE_FRAGMENT); +exports.PROPOSAL_QUERY = (0, graphql_tag_1.default)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n query ($id: String!) {\n sxproposal(id: $id) {\n ...highlightProposalFragment\n }\n }\n ", "\n"], ["\n query ($id: String!) {\n sxproposal(id: $id) {\n ...highlightProposalFragment\n }\n }\n ", "\n"])), PROPOSAL_FRAGMENT); +exports.PROPOSALS_QUERY = (0, graphql_tag_1.default)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n query ($ids: [String!]!) {\n sxproposals(where: { id_in: $ids }) {\n ...highlightProposalFragment\n }\n }\n ", "\n"], ["\n query ($ids: [String!]!) {\n sxproposals(where: { id_in: $ids }) {\n ...highlightProposalFragment\n }\n }\n ", "\n"])), PROPOSAL_FRAGMENT); +exports.VOTES_QUERY = (0, graphql_tag_1.default)(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n query ($space: String!, $proposal: Int!) {\n votes(where: { space: $space, proposal: $proposal }) {\n voter {\n id\n }\n space {\n id\n }\n proposal\n choice\n vp\n created\n tx\n }\n }\n"], ["\n query ($space: String!, $proposal: Int!) {\n votes(where: { space: $space, proposal: $proposal }) {\n voter {\n id\n }\n space {\n id\n }\n proposal\n choice\n vp\n created\n tx\n }\n }\n"]))); +exports.USER_QUERY = (0, graphql_tag_1.default)(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n query ($id: String!) {\n sxuser(id: $id) {\n id\n proposal_count\n vote_count\n created\n }\n }\n"], ["\n query ($id: String!) {\n sxuser(id: $id) {\n id\n proposal_count\n vote_count\n created\n }\n }\n"]))); +function joinHighlightSpace(space, highlightSpace) { + if (!highlightSpace) + return space; + return __assign(__assign({}, space), { vote_count: space.vote_count + highlightSpace.vote_count }); +} +function joinHighlightProposal(proposal, highlightProposal) { + if (!highlightProposal) + return proposal; + return __assign(__assign({}, proposal), { scores_1: Number(BigInt(proposal.scores_1) + BigInt(highlightProposal.scores_1)), scores_2: Number(BigInt(proposal.scores_2) + BigInt(highlightProposal.scores_2)), scores_3: Number(BigInt(proposal.scores_3) + BigInt(highlightProposal.scores_3)), scores_total: Number(BigInt(proposal.scores_total) + BigInt(highlightProposal.scores_total)), vote_count: proposal.vote_count + highlightProposal.vote_count }); +} +function joinHighlightUser(user, highlightUser) { + if (!highlightUser) + return user; + return __assign(__assign(__assign({}, user), highlightUser), { vote_count: user + ? user.vote_count + highlightUser.vote_count + : highlightUser.vote_count }); +} +function mixinHighlightVotes(votes, highlightVotes, filter, orderBy, orderDirection, limit) { + var _a; + if (!highlightVotes.length) + return { result: votes, remaining: [] }; + var filteredHighlightVotes = highlightVotes.filter(function (vote) { + if (filter === "for") + return vote.choice === 1; + if (filter === "against") + return vote.choice === 2; + if (filter === "abstain") + return vote.choice === 3; + return true; + }); + var hasMore = votes.length === limit; + var thresholdValue = votes.length > 0 ? (_a = votes[votes.length - 1]) === null || _a === void 0 ? void 0 : _a[orderBy] : null; + var mixins = !hasMore || thresholdValue === null + ? { added: filteredHighlightVotes, remaining: [] } + : filteredHighlightVotes.reduce(function (res, vote) { + var valid = orderDirection === "desc" + ? vote[orderBy] >= (thresholdValue !== null && thresholdValue !== void 0 ? thresholdValue : 0) + : vote[orderBy] < (thresholdValue !== null && thresholdValue !== void 0 ? thresholdValue : 0); + if (valid) + res.added.push(vote); + else + res.remaining.push(vote); + return res; + }, { added: [], remaining: [] }); + var result = __spreadArray(__spreadArray([], votes, true), mixins.added, true).sort(function (a, b) { + return orderDirection === "desc" + ? b[orderBy] - a[orderBy] + : a[orderBy] - b[orderBy]; + }); + return { result: result, remaining: mixins.remaining }; +} +var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8; diff --git a/apps/frontinus-house/src/lib/network/common/index.js b/apps/frontinus-house/src/lib/network/common/index.js new file mode 100644 index 00000000..4463482b --- /dev/null +++ b/apps/frontinus-house/src/lib/network/common/index.js @@ -0,0 +1,463 @@ +"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 (g && (g = 0, op[0] && (_ = 0)), _) 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createApi = createApi; +var constants_1 = require("@/data/constants"); +var stamp_1 = require("@/lib/stamp"); +var core_1 = require("@apollo/client/core"); +var highlight_1 = require("./highlight"); +var queries_1 = require("./queries"); +function getProposalState(proposal, current) { + if (proposal.executed) + return "executed"; + if (proposal.max_end <= current) { + if (proposal.scores_total < proposal.quorum) + return "rejected"; + return proposal.scores_1 > proposal.scores_2 ? "passed" : "rejected"; + } + if (proposal.start > current) + return "pending"; + return "active"; +} +function formatExecution(execution) { + if (execution === "") + return []; + try { + var result = JSON.parse(execution); + return Array.isArray(result) ? result : []; + } + catch (e) { + console.log("Failed to parse execution"); + return []; + } +} +function processStrategiesMetadata(parsedMetadata, strategiesIndicies) { + if (parsedMetadata.length === 0) + return []; + var maxIndex = Math.max.apply(Math, parsedMetadata.map(function (metadata) { return metadata.index; })); + var metadataMap = Object.fromEntries(parsedMetadata.map(function (metadata) { return [ + metadata.index, + { + name: metadata.data.name, + description: metadata.data.description, + decimals: metadata.data.decimals, + symbol: metadata.data.symbol, + token: metadata.data.token, + payload: metadata.data.payload, + }, + ]; })); + strategiesIndicies = + strategiesIndicies || Array.from(Array(maxIndex + 1).keys()); + return strategiesIndicies.map(function (index) { return metadataMap[index]; }) || []; +} +function formatSpace(space, networkId) { + return __assign(__assign({}, space), { network: networkId, verified: false, turbo: false, name: space.metadata.name, avatar: space.metadata.avatar, cover: space.metadata.cover, about: space.metadata.about, external_url: space.metadata.external_url, github: space.metadata.github, twitter: space.metadata.twitter, discord: space.metadata.discord, voting_power_symbol: space.metadata.voting_power_symbol, treasuries: space.metadata.treasuries.map(function (treasury) { + var _a = JSON.parse(treasury), name = _a.name, network = _a.network, address = _a.address; + return { + name: name, + network: network, + address: address, + }; + }), delegations: space.metadata.delegations.map(function (delegation) { + var _a = JSON.parse(delegation), name = _a.name, api_type = _a.api_type, api_url = _a.api_url, contract = _a.contract; + var _b = contract.split(":"), network = _b[0], address = _b[1]; + return { + name: name, + apiType: api_type, + apiUrl: api_url, + contractNetwork: network === "null" ? null : network, + contractAddress: address === "null" ? null : address, + }; + }), executors: space.metadata.executors, executors_types: space.metadata.executors_types, executors_destinations: space.metadata.executors_destinations, executors_strategies: space.metadata.executors_strategies, + //@ts-expect-error undefined + voting_power_validation_strategies_parsed_metadata: processStrategiesMetadata(space.voting_power_validation_strategies_parsed_metadata), + //@ts-expect-error undefined + strategies_parsed_metadata: processStrategiesMetadata(space.strategies_parsed_metadata, space.strategies_indicies) }); +} +function formatProposal(proposal, networkId, current) { + return __assign(__assign({}, proposal), { space: { + id: proposal.space.id, + name: proposal.space.metadata.name, + avatar: proposal.space.metadata.avatar, + controller: proposal.space.controller, + authenticators: proposal.space.authenticators, + voting_power_symbol: proposal.space.metadata.voting_power_symbol, + executors: proposal.space.metadata.executors, + executors_types: proposal.space.metadata.executors_types, + //@ts-expect-error undefined + strategies_parsed_metadata: processStrategiesMetadata(proposal.space.strategies_parsed_metadata, proposal.strategies_indicies), + }, metadata_uri: proposal.metadata.id, type: "basic", choices: constants_1.BASIC_CHOICES, scores: [proposal.scores_1, proposal.scores_2, proposal.scores_3], title: proposal.metadata.title, body: proposal.metadata.body, discussion: proposal.metadata.discussion, execution: formatExecution(proposal.metadata.execution), has_execution_window_opened: proposal.execution_strategy_type === "Axiom" + ? proposal.max_end <= current + : proposal.min_end <= current, state: getProposalState(proposal, current), network: networkId, privacy: null, quorum: +proposal.quorum }); +} +function createApi(uri, networkId, opts) { + var _this = this; + if (opts === void 0) { opts = {}; } + var httpLink = (0, core_1.createHttpLink)({ uri: uri }); + var apollo = new core_1.ApolloClient({ + link: httpLink, + cache: new core_1.InMemoryCache({ + addTypename: false, + }), + defaultOptions: { + query: { + fetchPolicy: "no-cache", + }, + }, + }); + var highlightApolloClient = opts.highlightApiUrl + ? new core_1.ApolloClient({ + link: (0, core_1.createHttpLink)({ uri: opts.highlightApiUrl }), + cache: new core_1.InMemoryCache({ + addTypename: false, + }), + defaultOptions: { + query: { + fetchPolicy: "no-cache", + }, + }, + }) + : null; + var highlightVotesCache = { + key: null, + data: [], + remaining: [], + }; + return { + loadProposalVotes: function (proposal_1, _a) { + var args_1 = []; + for (var _i = 2; _i < arguments.length; _i++) { + args_1[_i - 2] = arguments[_i]; + } + return __awaiter(_this, __spreadArray([proposal_1, _a], args_1, true), void 0, function (proposal, _b, filter, sortBy) { + var filters, _c, orderBy, orderDirection, data, cacheKey, cacheValid, highlightData, _d, result, remaining, addresses, names; + var limit = _b.limit, _e = _b.skip, skip = _e === void 0 ? 0 : _e; + if (filter === void 0) { filter = "any"; } + if (sortBy === void 0) { sortBy = "vp-desc"; } + return __generator(this, function (_f) { + switch (_f.label) { + case 0: + filters = {}; + if (filter === "for") { + filters.choice = 1; + } + else if (filter === "against") { + filters.choice = 2; + } + else if (filter === "abstain") { + filters.choice = 3; + } + _c = sortBy.split("-"), orderBy = _c[0], orderDirection = _c[1]; + return [4 /*yield*/, apollo.query({ + query: queries_1.VOTES_QUERY, + variables: { + first: limit, + skip: skip, + orderBy: orderBy, + orderDirection: orderDirection, + where: __assign({ space: proposal.space.id, proposal: proposal.proposal_id }, filters), + }, + })]; + case 1: + data = (_f.sent()).data; + if (!highlightApolloClient) return [3 /*break*/, 5]; + cacheKey = "".concat(proposal.space.id, "/").concat(proposal.proposal_id); + cacheValid = highlightVotesCache.key === cacheKey; + if (!!cacheValid) return [3 /*break*/, 3]; + return [4 /*yield*/, highlightApolloClient.query({ + query: highlight_1.VOTES_QUERY, + variables: { + space: proposal.space.id, + proposal: proposal.proposal_id, + }, + })]; + case 2: + highlightData = (_f.sent()).data; + highlightVotesCache.key = cacheKey; + highlightVotesCache.data = highlightData.votes; + highlightVotesCache.remaining = highlightData.votes; + return [3 /*break*/, 4]; + case 3: + if (skip === 0) { + highlightVotesCache.remaining = highlightVotesCache.data; + } + _f.label = 4; + case 4: + _d = (0, highlight_1.mixinHighlightVotes)(data.votes, highlightVotesCache.remaining, filter, orderBy, orderDirection, limit), result = _d.result, remaining = _d.remaining; + highlightVotesCache.remaining = remaining; + data.votes = result; + _f.label = 5; + case 5: + addresses = data.votes.map(function (vote) { return vote.voter.id; }); + return [4 /*yield*/, (0, stamp_1.getNames)(addresses)]; + case 6: + names = _f.sent(); + return [2 /*return*/, data.votes.map(function (vote) { + vote.voter.name = names[vote.voter.id] || null; + return vote; + })]; + } + }); + }); + }, + loadUserVotes: function (spaceIds, voter) { return __awaiter(_this, void 0, void 0, function () { + var data; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, apollo.query({ + query: queries_1.USER_VOTES_QUERY, + variables: { + spaceIds: spaceIds, + voter: voter, + }, + })]; + case 1: + data = (_a.sent()).data; + return [2 /*return*/, Object.fromEntries(data.votes.map(function (vote) { return [ + "".concat(networkId, ":").concat(vote.space.id, "/").concat(vote.proposal), + vote, + ]; }))]; + } + }); + }); }, + loadProposals: function (spaceIds_1, _a, current_1) { + var args_1 = []; + for (var _i = 3; _i < arguments.length; _i++) { + args_1[_i - 3] = arguments[_i]; + } + return __awaiter(_this, __spreadArray([spaceIds_1, _a, current_1], args_1, true), void 0, function (spaceIds, _b, current, filter, searchQuery) { + var filters, data, highlightData_1; + var limit = _b.limit, _c = _b.skip, skip = _c === void 0 ? 0 : _c; + if (filter === void 0) { filter = "any"; } + if (searchQuery === void 0) { searchQuery = ""; } + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + filters = {}; + if (filter === "active") { + filters.start_lte = current; + filters.max_end_gte = current; + } + else if (filter === "pending") { + filters.start_gt = current; + } + else if (filter === "closed") { + filters.max_end_lt = current; + } + return [4 /*yield*/, apollo.query({ + query: queries_1.PROPOSALS_QUERY, + variables: { + first: limit, + skip: skip, + where: __assign({ space_in: spaceIds, cancelled: false, metadata_: { title_contains_nocase: searchQuery } }, filters), + }, + })]; + case 1: + data = (_d.sent()).data; + console.log(data); + if (!highlightApolloClient) return [3 /*break*/, 3]; + return [4 /*yield*/, highlightApolloClient.query({ + query: highlight_1.PROPOSALS_QUERY, + variables: { + ids: data.proposals.map(function (proposal) { return proposal.id; }), + }, + })]; + case 2: + highlightData_1 = (_d.sent()).data; + data.proposals = data.proposals.map(function (proposal) { + var highlightProposal = highlightData_1.sxproposals.find(function (highlightProposal) { return highlightProposal.id === proposal.id; }); + return (0, highlight_1.joinHighlightProposal)(proposal, highlightProposal); + }); + _d.label = 3; + case 3: return [2 /*return*/, data.proposals.map(function (proposal) { + return formatProposal(proposal, networkId, current); + })]; + } + }); + }); + }, + loadProposal: function (spaceId, proposalId, current) { return __awaiter(_this, void 0, void 0, function () { + var _a, data, highlightResult; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, Promise.all([ + apollo.query({ + query: queries_1.PROPOSAL_QUERY, + variables: { id: "".concat(spaceId, "/").concat(proposalId) }, + }), + highlightApolloClient === null || highlightApolloClient === void 0 ? void 0 : highlightApolloClient.query({ + query: highlight_1.PROPOSAL_QUERY, + variables: { id: "".concat(spaceId, "/").concat(proposalId) }, + }).catch(function () { return null; }), + ])]; + case 1: + _a = _b.sent(), data = _a[0].data, highlightResult = _a[1]; + if (data.proposal.metadata === null) + return [2 /*return*/, null]; + data.proposal = (0, highlight_1.joinHighlightProposal)(data.proposal, highlightResult === null || highlightResult === void 0 ? void 0 : highlightResult.data.sxproposal); + return [2 /*return*/, formatProposal(data.proposal, networkId, current)]; + } + }); + }); }, + loadSpaces: function (_a, filter_1) { return __awaiter(_this, [_a, filter_1], void 0, function (_b, filter) { + var data, highlightData_2; + var limit = _b.limit, _c = _b.skip, skip = _c === void 0 ? 0 : _c; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: return [4 /*yield*/, apollo.query({ + query: queries_1.SPACES_QUERY, + variables: { + first: limit, + skip: skip, + where: __assign(__assign({}, filter), { metadata_: {} }), + }, + })]; + case 1: + data = (_d.sent()).data; + if (!highlightApolloClient) return [3 /*break*/, 3]; + return [4 /*yield*/, highlightApolloClient.query({ + query: highlight_1.SPACES_QUERY, + variables: { ids: data.spaces.map(function (space) { return space.id; }) }, + })]; + case 2: + highlightData_2 = (_d.sent()).data; + data.spaces = data.spaces.map(function (space) { + var highlightSpace = highlightData_2.sxspaces.find(function (highlightSpace) { return highlightSpace.id === space.id; }); + return (0, highlight_1.joinHighlightSpace)(space, highlightSpace); + }); + _d.label = 3; + case 3: return [2 /*return*/, data.spaces.map(function (space) { return formatSpace(space, networkId); })]; + } + }); + }); }, + loadSpace: function (id) { return __awaiter(_this, void 0, void 0, function () { + var _a, data, highlightResult; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, Promise.all([ + apollo.query({ + query: queries_1.SPACE_QUERY, + variables: { id: id }, + }), + highlightApolloClient === null || highlightApolloClient === void 0 ? void 0 : highlightApolloClient.query({ + query: highlight_1.SPACE_QUERY, + variables: { id: id }, + }).catch(function () { return null; }), + ])]; + case 1: + _a = _b.sent(), data = _a[0].data, highlightResult = _a[1]; + data.space = (0, highlight_1.joinHighlightSpace)(data.space, highlightResult === null || highlightResult === void 0 ? void 0 : highlightResult.data.sxspace); + return [2 /*return*/, formatSpace(data.space, networkId)]; + } + }); + }); }, + loadUser: function (id) { return __awaiter(_this, void 0, void 0, function () { + var _a, data, highlightResult; + var _b, _c, _d; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: return [4 /*yield*/, Promise.all([ + apollo.query({ + query: queries_1.USER_QUERY, + variables: { id: id }, + }), + highlightApolloClient === null || highlightApolloClient === void 0 ? void 0 : highlightApolloClient.query({ + query: highlight_1.USER_QUERY, + variables: { id: id }, + }).catch(function () { return null; }), + ])]; + case 1: + _a = _e.sent(), data = _a[0].data, highlightResult = _a[1]; + return [2 /*return*/, (0, highlight_1.joinHighlightUser)((_b = data.user) !== null && _b !== void 0 ? _b : null, (_d = (_c = highlightResult === null || highlightResult === void 0 ? void 0 : highlightResult.data) === null || _c === void 0 ? void 0 : _c.sxuser) !== null && _d !== void 0 ? _d : null)]; + } + }); + }); }, + loadLeaderboard: function (spaceId, _a, sortBy) { + var limit = _a.limit, _b = _a.skip, skip = _b === void 0 ? 0 : _b; + if (sortBy === void 0) { sortBy = "vote_count-desc"; } + var _c = sortBy.split("-"), orderBy = _c[0], orderDirection = _c[1]; + return apollo + .query({ + query: queries_1.LEADERBOARD_QUERY, + variables: { + first: limit, + skip: skip, + orderBy: orderBy, + orderDirection: orderDirection, + where: { + space: spaceId, + }, + }, + }) + .then(function (_a) { + var data = _a.data; + return data.leaderboards.map(function (leaderboard) { return ({ + id: leaderboard.user.id, + created: leaderboard.user.created, + vote_count: leaderboard.vote_count, + proposal_count: leaderboard.proposal_count, + }); }); + }); + }, + loadFollows: function () { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, []]; + }); + }); }, + }; +} diff --git a/apps/frontinus-house/src/lib/network/common/queries.js b/apps/frontinus-house/src/lib/network/common/queries.js new file mode 100644 index 00000000..cc97f677 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/common/queries.js @@ -0,0 +1,19 @@ +"use strict"; +var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LEADERBOARD_QUERY = exports.USER_QUERY = exports.SPACES_QUERY = exports.SPACE_QUERY = exports.USER_VOTES_QUERY = exports.VOTES_QUERY = exports.PROPOSALS_QUERY = exports.PROPOSAL_QUERY = void 0; +var graphql_tag_1 = require("graphql-tag"); +var SPACE_FRAGMENT = (0, graphql_tag_1.default)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n fragment spaceFragment on Space {\n id\n metadata {\n name\n avatar\n cover\n about\n external_url\n github\n twitter\n discord\n voting_power_symbol\n treasuries\n delegations\n executors\n executors_types\n executors_destinations\n executors_strategies {\n id\n address\n destination_address\n type\n treasury_chain\n treasury\n }\n }\n controller\n voting_delay\n min_voting_period\n max_voting_period\n proposal_threshold\n validation_strategy\n validation_strategy_params\n voting_power_validation_strategy_strategies\n voting_power_validation_strategy_strategies_params\n voting_power_validation_strategies_parsed_metadata {\n index\n data {\n name\n description\n decimals\n symbol\n token\n payload\n }\n }\n strategies_indicies\n strategies\n strategies_params\n strategies_parsed_metadata {\n index\n data {\n name\n description\n decimals\n symbol\n token\n payload\n }\n }\n authenticators\n proposal_count\n vote_count\n created\n }\n"], ["\n fragment spaceFragment on Space {\n id\n metadata {\n name\n avatar\n cover\n about\n external_url\n github\n twitter\n discord\n voting_power_symbol\n treasuries\n delegations\n executors\n executors_types\n executors_destinations\n executors_strategies {\n id\n address\n destination_address\n type\n treasury_chain\n treasury\n }\n }\n controller\n voting_delay\n min_voting_period\n max_voting_period\n proposal_threshold\n validation_strategy\n validation_strategy_params\n voting_power_validation_strategy_strategies\n voting_power_validation_strategy_strategies_params\n voting_power_validation_strategies_parsed_metadata {\n index\n data {\n name\n description\n decimals\n symbol\n token\n payload\n }\n }\n strategies_indicies\n strategies\n strategies_params\n strategies_parsed_metadata {\n index\n data {\n name\n description\n decimals\n symbol\n token\n payload\n }\n }\n authenticators\n proposal_count\n vote_count\n created\n }\n"]))); +var PROPOSAL_FRAGMENT = (0, graphql_tag_1.default)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n fragment proposalFragment on Proposal {\n id\n proposal_id\n space {\n id\n controller\n authenticators\n metadata {\n id\n name\n avatar\n voting_power_symbol\n executors\n executors_types\n }\n strategies_parsed_metadata {\n index\n data {\n name\n description\n decimals\n symbol\n token\n payload\n }\n }\n }\n author {\n id\n }\n quorum\n execution_hash\n metadata {\n id\n title\n body\n discussion\n execution\n }\n start\n min_end\n max_end\n snapshot\n scores_1\n scores_2\n scores_3\n scores_total\n execution_time\n execution_strategy\n execution_strategy_type\n execution_destination\n timelock_veto_guardian\n strategies_indicies\n strategies\n strategies_params\n created\n edited\n tx\n execution_tx\n veto_tx\n vote_count\n execution_ready\n executed\n vetoed\n completed\n cancelled\n }\n"], ["\n fragment proposalFragment on Proposal {\n id\n proposal_id\n space {\n id\n controller\n authenticators\n metadata {\n id\n name\n avatar\n voting_power_symbol\n executors\n executors_types\n }\n strategies_parsed_metadata {\n index\n data {\n name\n description\n decimals\n symbol\n token\n payload\n }\n }\n }\n author {\n id\n }\n quorum\n execution_hash\n metadata {\n id\n title\n body\n discussion\n execution\n }\n start\n min_end\n max_end\n snapshot\n scores_1\n scores_2\n scores_3\n scores_total\n execution_time\n execution_strategy\n execution_strategy_type\n execution_destination\n timelock_veto_guardian\n strategies_indicies\n strategies\n strategies_params\n created\n edited\n tx\n execution_tx\n veto_tx\n vote_count\n execution_ready\n executed\n vetoed\n completed\n cancelled\n }\n"]))); +exports.PROPOSAL_QUERY = (0, graphql_tag_1.default)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n query ($id: String!) {\n proposal(id: $id) {\n ...proposalFragment\n }\n }\n ", "\n"], ["\n query ($id: String!) {\n proposal(id: $id) {\n ...proposalFragment\n }\n }\n ", "\n"])), PROPOSAL_FRAGMENT); +exports.PROPOSALS_QUERY = (0, graphql_tag_1.default)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n query ($first: Int!, $skip: Int!, $where: Proposal_filter) {\n proposals(\n first: $first\n skip: $skip\n where: $where\n orderBy: created\n orderDirection: desc\n ) {\n ...proposalFragment\n }\n }\n ", "\n"], ["\n query ($first: Int!, $skip: Int!, $where: Proposal_filter) {\n proposals(\n first: $first\n skip: $skip\n where: $where\n orderBy: created\n orderDirection: desc\n ) {\n ...proposalFragment\n }\n }\n ", "\n"])), PROPOSAL_FRAGMENT); +exports.VOTES_QUERY = (0, graphql_tag_1.default)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n query (\n $first: Int!\n $skip: Int!\n $orderBy: Vote_orderBy!\n $orderDirection: OrderDirection!\n $where: Vote_filter\n ) {\n votes(\n first: $first\n skip: $skip\n where: $where\n orderBy: $orderBy\n orderDirection: $orderDirection\n ) {\n id\n voter {\n id\n }\n space {\n id\n }\n proposal\n choice\n vp\n created\n tx\n }\n }\n"], ["\n query (\n $first: Int!\n $skip: Int!\n $orderBy: Vote_orderBy!\n $orderDirection: OrderDirection!\n $where: Vote_filter\n ) {\n votes(\n first: $first\n skip: $skip\n where: $where\n orderBy: $orderBy\n orderDirection: $orderDirection\n ) {\n id\n voter {\n id\n }\n space {\n id\n }\n proposal\n choice\n vp\n created\n tx\n }\n }\n"]))); +exports.USER_VOTES_QUERY = (0, graphql_tag_1.default)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n query ($spaceIds: [String], $voter: String) {\n votes(where: { space_in: $spaceIds, voter: $voter }) {\n id\n voter {\n id\n }\n space {\n id\n }\n proposal\n choice\n vp\n created\n }\n }\n"], ["\n query ($spaceIds: [String], $voter: String) {\n votes(where: { space_in: $spaceIds, voter: $voter }) {\n id\n voter {\n id\n }\n space {\n id\n }\n proposal\n choice\n vp\n created\n }\n }\n"]))); +exports.SPACE_QUERY = (0, graphql_tag_1.default)(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n query ($id: String!) {\n space(id: $id) {\n ...spaceFragment\n }\n }\n ", "\n"], ["\n query ($id: String!) {\n space(id: $id) {\n ...spaceFragment\n }\n }\n ", "\n"])), SPACE_FRAGMENT); +exports.SPACES_QUERY = (0, graphql_tag_1.default)(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n query ($first: Int!, $skip: Int!, $where: Space_filter) {\n spaces(\n first: $first\n skip: $skip\n orderBy: vote_count\n orderDirection: desc\n where: $where\n ) {\n ...spaceFragment\n }\n }\n ", "\n"], ["\n query ($first: Int!, $skip: Int!, $where: Space_filter) {\n spaces(\n first: $first\n skip: $skip\n orderBy: vote_count\n orderDirection: desc\n where: $where\n ) {\n ...spaceFragment\n }\n }\n ", "\n"])), SPACE_FRAGMENT); +exports.USER_QUERY = (0, graphql_tag_1.default)(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n query ($id: String!) {\n user(id: $id) {\n id\n proposal_count\n vote_count\n created\n }\n }\n"], ["\n query ($id: String!) {\n user(id: $id) {\n id\n proposal_count\n vote_count\n created\n }\n }\n"]))); +exports.LEADERBOARD_QUERY = (0, graphql_tag_1.default)(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n query (\n $first: Int!\n $skip: Int!\n $orderBy: Leaderboard_orderBy\n $orderDirection: OrderDirection!\n $where: Leaderboard_filter\n ) {\n leaderboards(\n first: $first\n skip: $skip\n orderBy: $orderBy\n orderDirection: $orderDirection\n where: $where\n ) {\n id\n user {\n id\n created\n }\n proposal_count\n vote_count\n }\n }\n"], ["\n query (\n $first: Int!\n $skip: Int!\n $orderBy: Leaderboard_orderBy\n $orderDirection: OrderDirection!\n $where: Leaderboard_filter\n ) {\n leaderboards(\n first: $first\n skip: $skip\n orderBy: $orderBy\n orderDirection: $orderDirection\n where: $where\n ) {\n id\n user {\n id\n created\n }\n proposal_count\n vote_count\n }\n }\n"]))); +var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10; diff --git a/apps/frontinus-house/src/lib/network/common/types.js b/apps/frontinus-house/src/lib/network/common/types.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/common/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/apps/frontinus-house/src/lib/network/evm/actions.js b/apps/frontinus-house/src/lib/network/evm/actions.js new file mode 100644 index 00000000..1c73c8c4 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/evm/actions.js @@ -0,0 +1,467 @@ +"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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createActions = createActions; +var constants_1 = require("@/data/constants"); +var link_1 = require("@/lib/link"); +var mana_1 = require("@/lib/mana"); +var constants_2 = require("@/lib/network/common/constants"); +var helpers_1 = require("@/lib/network/common/helpers"); +var transactions_1 = require("@/lib/transactions"); +var utils_1 = require("@/lib/utils"); +var contracts_1 = require("@ethersproject/contracts"); +var sx_1 = require("@snapshot-labs/sx"); +var CONFIGS = { + 1: sx_1.evmMainnet, + 11155111: sx_1.evmSepolia, +}; +function createActions(provider, helpers, chainId) { + var _this = this; + var networkConfig = CONFIGS[chainId]; + var pickAuthenticatorAndStrategies = (0, helpers_1.createStrategyPicker)({ + helpers: helpers, + managerConnectors: constants_2.EVM_CONNECTORS, + }); + if (!networkConfig) { + throw new Error("Network configuration is undefined"); + } + var client = new sx_1.clients.EvmEthereumTx({ networkConfig: networkConfig }); + var ethSigClient = new sx_1.clients.EvmEthereumSig({ + networkConfig: networkConfig, + manaUrl: mana_1.MANA_URL, + }); + var getIsContract = function (address) { return __awaiter(_this, void 0, void 0, function () { + var code; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, provider.getCode(address)]; + case 1: + code = _a.sent(); + return [2 /*return*/, code !== "0x"]; + } + }); + }); }; + return { + propose: function (web3, connectorType, account, space, cid, executionStrategy, transactions) { return __awaiter(_this, void 0, void 0, function () { + var isContract, _a, relayerType, authenticator, strategies, selectedExecutionStrategy, strategiesWithMetadata, data; + var _this = this; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _b.sent(); + return [4 /*yield*/, getIsContract(account)]; + case 2: + isContract = _b.sent(); + _a = pickAuthenticatorAndStrategies({ + authenticators: space.authenticators, + strategies: space.voting_power_validation_strategy_strategies, + strategiesIndicies: space.voting_power_validation_strategy_strategies.map(function (_, i) { return i; }), + connectorType: connectorType, + isContract: isContract, + }), relayerType = _a.relayerType, authenticator = _a.authenticator, strategies = _a.strategies; + if (executionStrategy) { + selectedExecutionStrategy = { + addr: executionStrategy, + params: (0, helpers_1.getExecutionData)(space, executionStrategy, transactions) + .executionParams[0], + }; + } + else { + selectedExecutionStrategy = { + addr: "0x0000000000000000000000000000000000000000", + params: "0x", + }; + } + return [4 /*yield*/, Promise.all(strategies.map(function (strategy) { return __awaiter(_this, void 0, void 0, function () { + var metadata; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, helpers_1.parseStrategyMetadata)(space.voting_power_validation_strategies_parsed_metadata[strategy.index].payload)]; + case 1: + metadata = _a.sent(); + return [2 /*return*/, __assign(__assign({}, strategy), { metadata: metadata })]; + } + }); + }); }))]; + case 3: + strategiesWithMetadata = _b.sent(); + data = { + space: space.id, + authenticator: authenticator, + strategies: strategiesWithMetadata, + executionStrategy: selectedExecutionStrategy, + metadataUri: "ipfs://".concat(cid), + }; + if (relayerType === "evm") { + return [2 /*return*/, ethSigClient.propose({ + signer: web3.getSigner(), + data: data, + })]; + } + return [2 /*return*/, client.propose({ + signer: web3.getSigner(), + envelope: { + data: data, + }, + }, { + noWait: isContract, + })]; + } + }); + }); }, + updateProposal: function (web3, connectorType, account, space, proposalId, cid, executionStrategy, transactions) { + return __awaiter(this, void 0, void 0, function () { + var isContract, _a, relayerType, authenticator, selectedExecutionStrategy, data; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _b.sent(); + return [4 /*yield*/, getIsContract(account)]; + case 2: + isContract = _b.sent(); + _a = pickAuthenticatorAndStrategies({ + authenticators: space.authenticators, + strategies: space.voting_power_validation_strategy_strategies, + strategiesIndicies: space.voting_power_validation_strategy_strategies.map(function (_, i) { return i; }), + connectorType: connectorType, + isContract: isContract, + }), relayerType = _a.relayerType, authenticator = _a.authenticator; + if (executionStrategy) { + selectedExecutionStrategy = { + addr: executionStrategy, + params: (0, helpers_1.getExecutionData)(space, executionStrategy, transactions) + .executionParams[0], + }; + } + else { + selectedExecutionStrategy = { + addr: "0x0000000000000000000000000000000000000000", + params: "0x", + }; + } + data = { + space: space.id, + proposal: proposalId, + authenticator: authenticator, + executionStrategy: selectedExecutionStrategy, + metadataUri: "ipfs://".concat(cid), + }; + if (relayerType === "evm") { + return [2 /*return*/, ethSigClient.updateProposal({ + signer: web3.getSigner(), + data: data, + })]; + } + return [2 /*return*/, client.updateProposal({ + signer: web3.getSigner(), + envelope: { + data: data, + }, + }, { noWait: isContract })]; + } + }); + }); + }, + cancelProposal: function (web3, proposal) { return __awaiter(_this, void 0, void 0, function () { + var address, isContract; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _a.sent(); + return [4 /*yield*/, web3.getSigner().getAddress()]; + case 2: + address = _a.sent(); + return [4 /*yield*/, getIsContract(address)]; + case 3: + isContract = _a.sent(); + return [2 /*return*/, client.cancel({ + signer: web3.getSigner(), + space: proposal.space.id, + proposal: proposal.proposal_id, + }, { noWait: isContract })]; + } + }); + }); }, + vote: function (web3, connectorType, account, proposal, choice) { return __awaiter(_this, void 0, void 0, function () { + var isContract, _a, relayerType, authenticator, strategies, strategiesWithMetadata, data; + var _this = this; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _b.sent(); + return [4 /*yield*/, getIsContract(account)]; + case 2: + isContract = _b.sent(); + _a = pickAuthenticatorAndStrategies({ + authenticators: proposal.space.authenticators, + strategies: proposal.strategies, + strategiesIndicies: proposal.strategies_indicies, + connectorType: connectorType, + isContract: isContract, + }), relayerType = _a.relayerType, authenticator = _a.authenticator, strategies = _a.strategies; + return [4 /*yield*/, Promise.all(strategies.map(function (strategy) { return __awaiter(_this, void 0, void 0, function () { + var metadataIndex, metadata; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + metadataIndex = proposal.strategies_indicies.indexOf(strategy.index); + return [4 /*yield*/, (0, helpers_1.parseStrategyMetadata)(proposal.space.strategies_parsed_metadata[metadataIndex].payload)]; + case 1: + metadata = _a.sent(); + return [2 /*return*/, __assign(__assign({}, strategy), { metadata: metadata })]; + } + }); + }); }))]; + case 3: + strategiesWithMetadata = _b.sent(); + data = { + space: proposal.space.id, + authenticator: authenticator, + strategies: strategiesWithMetadata, + proposal: proposal.proposal_id, + choice: (0, helpers_1.getSdkChoice)(choice), + metadataUri: "", + chainId: chainId, + }; + /* if (!isContract && proposal.execution_strategy_type === 'Axiom') { + return highlightVote({ signer: web3.getSigner(), data }); + }*/ + if (relayerType === "evm") { + return [2 /*return*/, ethSigClient.vote({ + signer: web3.getSigner(), + data: data, + })]; + } + return [2 /*return*/, client.vote({ + signer: web3.getSigner(), + envelope: { + data: data, + }, + }, { noWait: isContract })]; + } + }); + }); }, + finalizeProposal: function (web3, proposal) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, mana_1.executionCall)(chainId, "finalizeProposal", { + space: proposal.space.id, + proposalId: proposal.proposal_id, + })]; + case 1: + _a.sent(); + return [2 /*return*/, null]; + } + }); + }); }, + executeTransactions: function (web3, proposal) { return __awaiter(_this, void 0, void 0, function () { + var executionData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _a.sent(); + executionData = (0, helpers_1.getExecutionData)(proposal.space, proposal.execution_strategy, (0, transactions_1.convertToMetaTransactions)(proposal.execution)); + return [2 /*return*/, (0, mana_1.executionCall)(chainId, "execute", { + space: proposal.space.id, + proposalId: proposal.proposal_id, + executionParams: executionData.executionParams[0], + })]; + } + }); + }); }, + executeQueuedProposal: function (web3, proposal) { return __awaiter(_this, void 0, void 0, function () { + var executionData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _a.sent(); + executionData = (0, helpers_1.getExecutionData)(proposal.space, proposal.execution_strategy, (0, transactions_1.convertToMetaTransactions)(proposal.execution)); + return [2 /*return*/, (0, mana_1.executionCall)(chainId, "executeQueuedProposal", { + space: proposal.space.id, + executionStrategy: proposal.execution_strategy, + executionParams: executionData.executionParams[0], + })]; + } + }); + }); }, + vetoProposal: function (web3, proposal) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _a.sent(); + return [2 /*return*/, client.vetoExecution({ + signer: web3.getSigner(), + executionStrategy: proposal.execution_strategy, + executionHash: proposal.execution_hash, + })]; + } + }); + }); }, + setVotingDelay: function (web3, space, votingDelay) { return __awaiter(_this, void 0, void 0, function () { + var address, isContract; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _a.sent(); + return [4 /*yield*/, web3.getSigner().getAddress()]; + case 2: + address = _a.sent(); + return [4 /*yield*/, getIsContract(address)]; + case 3: + isContract = _a.sent(); + return [2 /*return*/, client.setVotingDelay({ + signer: web3.getSigner(), + space: space.id, + votingDelay: votingDelay, + }, { noWait: isContract })]; + } + }); + }); }, + setMinVotingDuration: function (web3, space, minVotingDuration) { return __awaiter(_this, void 0, void 0, function () { + var address, isContract; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _a.sent(); + return [4 /*yield*/, web3.getSigner().getAddress()]; + case 2: + address = _a.sent(); + return [4 /*yield*/, getIsContract(address)]; + case 3: + isContract = _a.sent(); + return [2 /*return*/, client.setMinVotingDuration({ + signer: web3.getSigner(), + space: space.id, + minVotingDuration: minVotingDuration, + }, { noWait: isContract })]; + } + }); + }); }, + setMaxVotingDuration: function (web3, space, maxVotingDuration) { return __awaiter(_this, void 0, void 0, function () { + var address, isContract; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, chainId)]; + case 1: + _a.sent(); + return [4 /*yield*/, web3.getSigner().getAddress()]; + case 2: + address = _a.sent(); + return [4 /*yield*/, getIsContract(address)]; + case 3: + isContract = _a.sent(); + return [2 /*return*/, client.setMaxVotingDuration({ + signer: web3.getSigner(), + space: space.id, + maxVotingDuration: maxVotingDuration, + }, { noWait: isContract })]; + } + }); + }); }, + delegate: function (web3, space, networkId, delegatee, delegationContract) { return __awaiter(_this, void 0, void 0, function () { + var _a, contractAddress, votesContract; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, constants_1.CHAIN_IDS[networkId])]; + case 1: + _b.sent(); + _a = delegationContract.split(":"), contractAddress = _a[1]; + votesContract = new contracts_1.Contract(contractAddress, ["function delegate(address delegatee)"], web3.getSigner()); + return [2 /*return*/, votesContract.delegate(delegatee)]; + } + }); + }); }, + send: function (envelope) { return ethSigClient.send(envelope); }, + getVotingPower: function (spaceId, strategiesAddresses, strategiesParams, strategiesMetadata, voterAddress, snapshotInfo) { return __awaiter(_this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + if (snapshotInfo.at === null) + throw new Error("EVM requires block number to be defined"); + return [2 /*return*/, Promise.all(strategiesAddresses.map(function (address, i) { return __awaiter(_this, void 0, void 0, function () { + var strategy, strategyMetadata, value, token; + var _a, _b, _c, _d; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + strategy = (0, sx_1.getEvmStrategy)(address, networkConfig); + if (!strategy) + return [2 /*return*/, { address: address, value: 0n, decimals: 0, token: null, symbol: "" }]; + return [4 /*yield*/, (0, helpers_1.parseStrategyMetadata)(strategiesMetadata[i].payload)]; + case 1: + strategyMetadata = _e.sent(); + return [4 /*yield*/, strategy.getVotingPower(address, voterAddress, strategyMetadata, snapshotInfo.at, strategiesParams[i], provider)]; + case 2: + value = _e.sent(); + token = ["comp", "ozVotes"].includes(strategy.type) + ? strategiesParams[i] + : undefined; + return [2 /*return*/, { + address: address, + value: value, + decimals: (_b = (_a = strategiesMetadata[i]) === null || _a === void 0 ? void 0 : _a.decimals) !== null && _b !== void 0 ? _b : 0, + symbol: (_d = (_c = strategiesMetadata[i]) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : "", + token: token, + swapLink: (0, link_1.getSwapLink)(strategy.type, address, chainId), + }]; + } + }); + }); }))]; + }); + }); }, + }; +} diff --git a/apps/frontinus-house/src/lib/network/evm/index.js b/apps/frontinus-house/src/lib/network/evm/index.js new file mode 100644 index 00000000..fc532960 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/evm/index.js @@ -0,0 +1,62 @@ +"use strict"; +var _a; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.METADATA = void 0; +exports.createEvmNetwork = createEvmNetwork; +var networks_json_1 = require("@/data/networks.json"); +var provider_1 = require("@/lib/provider"); +var common_1 = require("../common"); +var constants_1 = require("../common/constants"); +var actions_1 = require("./actions"); +// shared for both ETH mainnet and ARB1 +var ETH_MAINNET_BLOCK_TIME = 12.09; +exports.METADATA = { + eth: { + name: "Ethereum", + chainId: 1, + apiUrl: "https://api.studio.thegraph.com/query/23545/sx/version/latest", + avatar: "ipfs://bafkreid7ndxh6y2ljw2jhbisodiyrhcy2udvnwqgon5wgells3kh4si5z4", + blockTime: ETH_MAINNET_BLOCK_TIME, + }, + sep: { + name: "Ethereum Sepolia", + chainId: 11155111, + apiUrl: (_a = import.meta.env.VITE_EVM_SEPOLIA_API) !== null && _a !== void 0 ? _a : "https://api.studio.thegraph.com/query/23545/sx-sepolia/version/latest", + avatar: "ipfs://bafkreid7ndxh6y2ljw2jhbisodiyrhcy2udvnwqgon5wgells3kh4si5z4", + blockTime: 13.2816, + }, +}; +function createEvmNetwork(networkId) { + var _a = exports.METADATA[networkId], name = _a.name, chainId = _a.chainId, currentChainId = _a.currentChainId, apiUrl = _a.apiUrl, avatar = _a.avatar; + var provider = (0, provider_1.getProvider)(chainId); + var api = (0, common_1.createApi)(apiUrl, networkId, { + highlightApiUrl: import.meta.env.VITE_HIGHLIGHT_URL, + }); + var helpers = { + waitForTransaction: function (txId) { return provider.waitForTransaction(txId); }, + getExplorerUrl: function (id, type) { + var dataType = "tx"; + if (type === "token") + dataType = "token"; + else if (["address", "contract", "strategy"].includes(type)) + dataType = "address"; + //@ts-expect-error json + return "".concat(networks_json_1.default[chainId].explorer, "/").concat(dataType, "/").concat(id); + }, + }; + return { + name: name, + avatar: avatar, + currentUnit: "block", + chainId: chainId, + baseChainId: chainId, + currentChainId: currentChainId !== null && currentChainId !== void 0 ? currentChainId : chainId, + supportsSimulation: ["eth", "sep"].includes(networkId), + managerConnectors: constants_1.EVM_CONNECTORS, + //@ts-expect-error incorrect helpers TODO + actions: (0, actions_1.createActions)(provider, helpers, chainId), + api: api, + //@ts-expect-error incorrect helpers TODO + helpers: helpers, + }; +} diff --git a/apps/frontinus-house/src/lib/network/index.js b/apps/frontinus-house/src/lib/network/index.js new file mode 100644 index 00000000..2eaa0f2b --- /dev/null +++ b/apps/frontinus-house/src/lib/network/index.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.supportsNullCurrent = exports.enabledReadWriteNetworks = exports.getReadWriteNetwork = exports.getNetwork = exports.evmNetworks = exports.enabledNetworks = void 0; +var starknet_1 = require("./starknet"); +var evm_1 = require("./evm"); +var starknetNetwork = (0, starknet_1.createStarknetNetwork)("sn"); +var starknetSepoliaNetwork = (0, starknet_1.createStarknetNetwork)("sn-sep"); +var ethereumNetwork = (0, evm_1.createEvmNetwork)("eth"); +var sepoliaNetwork = (0, evm_1.createEvmNetwork)("sep"); +exports.enabledNetworks = import.meta.env + .VITE_ENABLED_NETWORKS + ? import.meta.env.VITE_ENABLED_NETWORKS.split(",") + : ["sn", "sn-sep"]; +exports.evmNetworks = ["eth", "sep"]; +var getNetwork = function (id) { + if (!exports.enabledNetworks.includes(id)) + throw new Error("Network ".concat(id, " is not enabled")); + if (id === "eth") + return ethereumNetwork; + if (id === "sep") + return sepoliaNetwork; + if (id === "sn") + return starknetNetwork; + if (id === "sn-sep") + return starknetSepoliaNetwork; + throw new Error("Unknown network ".concat(id)); +}; +exports.getNetwork = getNetwork; +var getReadWriteNetwork = function (id) { + var network = (0, exports.getNetwork)(id); + if (network.readOnly) + throw new Error("Network ".concat(id, " is read-only")); + return network; +}; +exports.getReadWriteNetwork = getReadWriteNetwork; +exports.enabledReadWriteNetworks = exports.enabledNetworks.filter(function (id) { return !(0, exports.getNetwork)(id).readOnly; }); +/** + * supportsNullCurrent return true if the network supports null current to be used for computing current voting power + * @param networkId Network ID + * @returns boolean true if the network supports null current + */ +var supportsNullCurrent = function (networkID) { + return !exports.evmNetworks.includes(networkID); +}; +exports.supportsNullCurrent = supportsNullCurrent; diff --git a/apps/frontinus-house/src/lib/network/starknet/actions.js b/apps/frontinus-house/src/lib/network/starknet/actions.js new file mode 100644 index 00000000..db91997b --- /dev/null +++ b/apps/frontinus-house/src/lib/network/starknet/actions.js @@ -0,0 +1,520 @@ +"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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createActions = createActions; +var mana_1 = require("@/lib/mana"); +var constants_1 = require("@/lib/network/common/constants"); +var helpers_1 = require("@/lib/network/common/helpers"); +var provider_1 = require("@/lib/provider"); +var transactions_1 = require("@/lib/transactions"); +var utils_1 = require("@/lib/utils"); +var sx_1 = require("@snapshot-labs/sx"); +var starknet_1 = require("starknet"); +var CONFIGS = { + sn: sx_1.starknetMainnet, + "sn-sep": sx_1.starknetSepolia, +}; +function createActions(networkId, starkProvider, helpers, _a) { + var _this = this; + var chainId = _a.chainId, l1ChainId = _a.l1ChainId, ethUrl = _a.ethUrl; + var networkConfig = CONFIGS[networkId]; + if (!networkConfig) + throw new Error("Unsupported network ".concat(networkId)); + var l1Provider = (0, provider_1.getProvider)(l1ChainId); + var clientConfig = { + starkProvider: starkProvider, + manaUrl: mana_1.MANA_URL, + ethUrl: ethUrl, + networkConfig: networkConfig, + }; + var pickAuthenticatorAndStrategies = (0, helpers_1.createStrategyPicker)({ + helpers: helpers, + managerConnectors: constants_1.STARKNET_CONNECTORS, + lowPriorityAuthenticators: ["evm-tx"], + }); + var getIsContract = function (connectorType, address) { return __awaiter(_this, void 0, void 0, function () { + var code; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!constants_1.EVM_CONNECTORS.includes(connectorType)) + return [2 /*return*/, false]; + return [4 /*yield*/, l1Provider.getCode(address)]; + case 1: + code = _a.sent(); + return [2 /*return*/, code !== "0x"]; + } + }); + }); }; + var client = new sx_1.clients.StarknetTx(clientConfig); + var starkSigClient = new sx_1.clients.StarknetSig(clientConfig); + var ethSigClient = new sx_1.clients.EthereumSig(clientConfig); + var ethTxClient = new sx_1.clients.EthereumTx(clientConfig); + var l1ExecutorClient = new sx_1.clients.L1Executor(); + return { + predictSpaceAddress: function (web3_1, _a) { + return __awaiter(this, arguments, void 0, function (web3, _b) { + var salt = _b.salt; + return __generator(this, function (_c) { + return [2 /*return*/, client.predictSpaceAddress({ + account: web3.provider.account, + saltNonce: salt, + })]; + }); + }); + }, + deployDependency: function (web3, params) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (!params.strategy.deploy) { + throw new Error("This strategy is not deployable"); + } + return [2 /*return*/, params.strategy.deploy(client, web3, params.controller, params.spaceAddress, params.strategy.params)]; + }); + }); + }, + propose: function (web3, connectorType, account, space, cid, executionStrategy, executionDestinationAddress, transactions) { return __awaiter(_this, void 0, void 0, function () { + var isContract, _a, relayerType, authenticator, strategies, selectedExecutionStrategy, strategiesWithMetadata, data; + var _this = this; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, getIsContract(connectorType, account)]; + case 1: + isContract = _b.sent(); + _a = pickAuthenticatorAndStrategies({ + authenticators: space.authenticators, + strategies: space.voting_power_validation_strategy_strategies, + strategiesIndicies: space.voting_power_validation_strategy_strategies.map(function (_, i) { return i; }), + connectorType: connectorType, + isContract: isContract, + }), relayerType = _a.relayerType, authenticator = _a.authenticator, strategies = _a.strategies; + if (!(relayerType && ["evm", "evm-tx"].includes(relayerType))) return [3 /*break*/, 3]; + return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, l1ChainId)]; + case 2: + _b.sent(); + _b.label = 3; + case 3: + if (executionStrategy) { + selectedExecutionStrategy = { + addr: executionStrategy, + params: (0, helpers_1.getExecutionData)(space, executionStrategy, executionDestinationAddress, transactions).executionParams, + }; + } + else { + selectedExecutionStrategy = { + addr: "0x0000000000000000000000000000000000000000", + params: [], + }; + } + return [4 /*yield*/, Promise.all(strategies.map(function (strategy) { return __awaiter(_this, void 0, void 0, function () { + var metadata; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, helpers_1.parseStrategyMetadata)(space.voting_power_validation_strategies_parsed_metadata[ + //@ts-expect-error index can be undefined? + strategy.index].payload)]; + case 1: + metadata = _a.sent(); + return [2 /*return*/, __assign(__assign({}, strategy), { metadata: metadata })]; + } + }); + }); }))]; + case 4: + strategiesWithMetadata = _b.sent(); + data = { + space: space.id, + authenticator: authenticator, + strategies: strategiesWithMetadata, + executionStrategy: selectedExecutionStrategy, + metadataUri: "ipfs://".concat(cid), + }; + if (relayerType === "starknet") { + return [2 /*return*/, starkSigClient.propose({ + signer: web3.provider.account, + //@ts-expect-error index can be undefined? + data: data, + })]; + } + else if (relayerType === "evm") { + return [2 /*return*/, ethSigClient.propose({ + signer: web3.getSigner(), + //@ts-expect-error index can be undefined? + data: data, + })]; + } + else if (relayerType === "evm-tx") { + //@ts-expect-error index can be undefined? + return [2 /*return*/, ethTxClient.initializePropose(web3.getSigner(), data, { + noWait: isContract, + })]; + } + return [2 /*return*/, client.propose(web3.provider.account, { + //@ts-expect-error index can be undefined? + data: data, + })]; + } + }); + }); }, + updateProposal: function (web3, connectorType, account, space, proposalId, cid, executionStrategy, executionDestinationAddress, transactions) { + return __awaiter(this, void 0, void 0, function () { + var isContract, _a, relayerType, authenticator, selectedExecutionStrategy, data; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, getIsContract(connectorType, account)]; + case 1: + isContract = _b.sent(); + _a = pickAuthenticatorAndStrategies({ + authenticators: space.authenticators, + strategies: space.voting_power_validation_strategy_strategies, + strategiesIndicies: space.voting_power_validation_strategy_strategies.map(function (_, i) { return i; }), + connectorType: connectorType, + isContract: isContract, + }), relayerType = _a.relayerType, authenticator = _a.authenticator; + if (!(relayerType && ["evm", "evm-tx"].includes(relayerType))) return [3 /*break*/, 3]; + return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, l1ChainId)]; + case 2: + _b.sent(); + _b.label = 3; + case 3: + if (executionStrategy) { + selectedExecutionStrategy = { + addr: executionStrategy, + params: (0, helpers_1.getExecutionData)(space, executionStrategy, executionDestinationAddress, transactions).executionParams, + }; + } + else { + selectedExecutionStrategy = { + addr: "0x0000000000000000000000000000000000000000", + params: [], + }; + } + data = { + space: space.id, + proposal: proposalId, + authenticator: authenticator, + executionStrategy: selectedExecutionStrategy, + metadataUri: "ipfs://".concat(cid), + }; + if (relayerType === "starknet") { + return [2 /*return*/, starkSigClient.updateProposal({ + signer: web3.provider.account, + data: data, + })]; + } + else if (relayerType === "evm") { + return [2 /*return*/, ethSigClient.updateProposal({ + signer: web3.getSigner(), + data: data, + })]; + } + else if (relayerType === "evm-tx") { + return [2 /*return*/, ethTxClient.initializeUpdateProposal(web3.getSigner(), data, { + noWait: isContract, + })]; + } + return [2 /*return*/, client.updateProposal(web3.provider.account, { + data: data, + })]; + } + }); + }); + }, + cancelProposal: function (web3, proposal) { + return client.cancelProposal({ + signer: web3.provider.account, + space: proposal.space.id, + proposal: proposal.proposal_id, + }); + }, + vote: function (web3, connectorType, account, proposal, choice) { return __awaiter(_this, void 0, void 0, function () { + var isContract, _a, relayerType, authenticator, strategies, strategiesWithMetadata, data; + var _this = this; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, getIsContract(connectorType, account)]; + case 1: + isContract = _b.sent(); + _a = pickAuthenticatorAndStrategies({ + authenticators: proposal.space.authenticators, + strategies: proposal.strategies, + strategiesIndicies: proposal.strategies_indicies, + connectorType: connectorType, + isContract: isContract, + }), relayerType = _a.relayerType, authenticator = _a.authenticator, strategies = _a.strategies; + if (!(relayerType && ["evm", "evm-tx"].includes(relayerType))) return [3 /*break*/, 3]; + return [4 /*yield*/, (0, utils_1.verifyNetwork)(web3, l1ChainId)]; + case 2: + _b.sent(); + _b.label = 3; + case 3: return [4 /*yield*/, Promise.all(strategies.map(function (strategy) { return __awaiter(_this, void 0, void 0, function () { + var metadataIndex, metadata; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + metadataIndex = proposal.strategies_indicies.indexOf( + //@ts-expect-error index can be undefined? + strategy.index); + return [4 /*yield*/, (0, helpers_1.parseStrategyMetadata)( + //@ts-expect-error index can be undefined? + proposal.space.strategies_parsed_metadata[metadataIndex].payload)]; + case 1: + metadata = _a.sent(); + return [2 /*return*/, __assign(__assign({}, strategy), { metadata: metadata })]; + } + }); + }); }))]; + case 4: + strategiesWithMetadata = _b.sent(); + data = { + space: proposal.space.id, + authenticator: authenticator, + strategies: strategiesWithMetadata, + proposal: proposal.proposal_id, + choice: (0, helpers_1.getSdkChoice)(choice), + }; + if (relayerType === "starknet") { + return [2 /*return*/, starkSigClient.vote({ + signer: web3.provider.account, + //@ts-expect-error index can be undefined? + data: data, + })]; + } + else if (relayerType === "evm") { + return [2 /*return*/, ethSigClient.vote({ + signer: web3.getSigner(), + //@ts-expect-error index can be undefined? + data: data, + })]; + } + else if (relayerType === "evm-tx") { + //@ts-expect-error index can be undefined? + return [2 /*return*/, ethTxClient.initializeVote(web3.getSigner(), data, { + noWait: isContract, + })]; + } + return [2 /*return*/, client.vote(web3.provider.account, { + //@ts-expect-error index can be undefined? + data: data, + })]; + } + }); + }); }, + finalizeProposal: function () { return null; }, + executeTransactions: function (web3, proposal) { return __awaiter(_this, void 0, void 0, function () { + var executionData; + return __generator(this, function (_a) { + executionData = (0, helpers_1.getExecutionData)(proposal.space, proposal.execution_strategy, proposal.execution_destination, (0, transactions_1.convertToMetaTransactions)(proposal.execution)); + return [2 /*return*/, (0, mana_1.executionCall)("stark", chainId, "execute", { + space: proposal.space.id, + proposalId: proposal.proposal_id, + executionParams: executionData.executionParams, + })]; + }); + }); }, + executeQueuedProposal: function (web3, proposal) { return __awaiter(_this, void 0, void 0, function () { + var activeVotingStrategies, proposalData, votesFor, votesAgainst, votesAbstain, executionParams, executionHash; + var _a, _b, _c, _d; + return __generator(this, function (_e) { + if (!proposal.execution_destination) + throw new Error("Execution destination is missing"); + activeVotingStrategies = proposal.strategies_indicies.reduce(function (acc, index) { + return acc | (1n << BigInt(index)); + }, 0n); + proposalData = { + startTimestamp: BigInt(proposal.start), + minEndTimestamp: BigInt(proposal.min_end), + maxEndTimestamp: BigInt(proposal.max_end), + finalizationStatus: 0, + executionPayloadHash: proposal.execution_hash, + executionStrategy: proposal.execution_strategy, + authorAddressType: 1, // <- hardcoded, needs to be indexed (0 for starknet, 1 for ethereum) + author: proposal.author.id, + activeVotingStrategies: activeVotingStrategies, + }; + votesFor = BigInt((_a = proposal.scores[0]) !== null && _a !== void 0 ? _a : 0); + votesAgainst = BigInt((_b = proposal.scores[1]) !== null && _b !== void 0 ? _b : 0); + votesAbstain = BigInt((_c = proposal.scores[2]) !== null && _c !== void 0 ? _c : 0); + executionParams = (0, helpers_1.getExecutionData)(proposal.space, proposal.execution_strategy, proposal.execution_destination, (0, transactions_1.convertToMetaTransactions)(proposal.execution)).executionParams; + executionHash = "".concat(executionParams[2]).concat((_d = executionParams[1]) === null || _d === void 0 ? void 0 : _d.slice(2)); + return [2 /*return*/, l1ExecutorClient.execute({ + signer: web3.getSigner(), + executor: proposal.execution_destination, + space: proposal.space.id, + proposal: proposalData, + votesFor: votesFor, + votesAgainst: votesAgainst, + votesAbstain: votesAbstain, + executionHash: executionHash, + transactions: (0, transactions_1.convertToMetaTransactions)(proposal.execution), + })]; + }); + }); }, + //@ts-expect-error TODO + vetoProposal: function () { return null; }, + setVotingDelay: function (web3, space, votingDelay) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, client.setVotingDelay({ + signer: web3.provider.account, + space: space.id, + votingDelay: votingDelay, + })]; + }); + }); }, + setMinVotingDuration: function (web3, space, minVotingDuration) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, client.setMinVotingDuration({ + signer: web3.provider.account, + space: space.id, + minVotingDuration: minVotingDuration, + })]; + }); + }); }, + setMaxVotingDuration: function (web3, space, maxVotingDuration) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, client.setMaxVotingDuration({ + signer: web3.provider.account, + space: space.id, + maxVotingDuration: maxVotingDuration, + })]; + }); + }); }, + transferOwnership: function (web3, space, owner) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, client.transferOwnership({ + signer: web3.provider.account, + space: space.id, + owner: owner, + })]; + }); + }); }, + updateStrategies: function (web3, space, authenticatorsToAdd, authenticatorsToRemove, votingStrategiesToAdd, votingStrategiesToRemove, validationStrategy) { return __awaiter(_this, void 0, void 0, function () { + var metadataUris, proposalValidationStrategyMetadataUri; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, Promise.all(votingStrategiesToAdd.map(function (config) { return (0, helpers_1.buildMetadata)(helpers, config); }))]; + case 1: + metadataUris = _a.sent(); + return [4 /*yield*/, (0, helpers_1.buildMetadata)(helpers, validationStrategy)]; + case 2: + proposalValidationStrategyMetadataUri = _a.sent(); + return [2 /*return*/, client.updateSettings({ + signer: web3.provider.account, + space: space.id, + settings: { + authenticatorsToAdd: authenticatorsToAdd.map(function (config) { return config.address; }), + authenticatorsToRemove: space.authenticators.filter(function (authenticator, index) { return authenticatorsToRemove.includes(index); }), + votingStrategiesToAdd: votingStrategiesToAdd.map(function (config) { return ({ + addr: config.address, + params: config.generateParams + ? config.generateParams(config.params) + : [], + }); }), + votingStrategiesToRemove: votingStrategiesToRemove.map(function (index) { var _a; return (_a = space.strategies_indicies[index]) !== null && _a !== void 0 ? _a : 0; }), + votingStrategyMetadataUrisToAdd: metadataUris, + proposalValidationStrategy: { + addr: validationStrategy.address, + params: validationStrategy.generateParams + ? validationStrategy.generateParams(validationStrategy.params) + : [], + }, + proposalValidationStrategyMetadataUri: proposalValidationStrategyMetadataUri, + }, + })]; + } + }); + }); }, + delegate: function (web3, space, networkId, delegatee, delegationContract) { return __awaiter(_this, void 0, void 0, function () { + var _a, contractAddress, account; + return __generator(this, function (_b) { + _a = delegationContract.split(":"), contractAddress = _a[1]; + account = web3.provider.account; + return [2 /*return*/, account.execute({ + contractAddress: contractAddress, + entrypoint: "delegate", + calldata: starknet_1.CallData.compile({ + delegatee: delegatee, + }), + })]; + }); + }); }, + getVotingPower: function (spaceId, strategiesAddresses, strategiesParams, strategiesMetadata, voterAddress, snapshotInfo) { return __awaiter(_this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2 /*return*/, Promise.all(strategiesAddresses.map(function (address, i) { return __awaiter(_this, void 0, void 0, function () { + var strategy, strategyMetadata, value; + var _a, _b, _c, _d, _e, _f; + return __generator(this, function (_g) { + switch (_g.label) { + case 0: + strategy = (0, sx_1.getStarknetStrategy)(address, networkConfig); + if (!strategy) + return [2 /*return*/, { address: address, value: 0n, decimals: 0, token: null, symbol: "" }]; + return [4 /*yield*/, (0, helpers_1.parseStrategyMetadata)( + //@ts-expect-error + strategiesMetadata[i].payload)]; + case 1: + strategyMetadata = _g.sent(); + return [4 /*yield*/, strategy.getVotingPower(address, voterAddress, strategyMetadata, snapshotInfo.at, strategiesParams[i].split(","), __assign(__assign({}, clientConfig), { networkConfig: networkConfig }))]; + case 2: + value = _g.sent(); + return [2 /*return*/, { + address: address, + value: value, + decimals: (_b = (_a = strategiesMetadata[i]) === null || _a === void 0 ? void 0 : _a.decimals) !== null && _b !== void 0 ? _b : 0, + symbol: (_d = (_c = strategiesMetadata[i]) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : "", + token: (_f = (_e = strategiesMetadata[i]) === null || _e === void 0 ? void 0 : _e.token) !== null && _f !== void 0 ? _f : null, + }]; + } + }); + }); }))]; + }); + }); }, + send: function (envelope) { return starkSigClient.send(envelope); }, // TODO: extract it out of client to common helper + }; +} diff --git a/apps/frontinus-house/src/lib/network/starknet/index.js b/apps/frontinus-house/src/lib/network/starknet/index.js new file mode 100644 index 00000000..e3bbd333 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/starknet/index.js @@ -0,0 +1,146 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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.METADATA = void 0; +exports.createStarknetNetwork = createStarknetNetwork; +var starknet_1 = require("starknet"); +var common_1 = require("../common"); +var constants_1 = require("../common/constants"); +var actions_1 = require("./actions"); +var provider_1 = require("./provider"); +exports.METADATA = { + sn: { + name: "Starknet", + chainId: starknet_1.constants.StarknetChainId.SN_MAIN, + baseChainId: 1, + baseNetworkId: "eth", + rpcUrl: "https://starknet-mainnet.infura.io/v3/".concat(import.meta.env.VITE_INFURA_API_KEY), + ethRpcUrl: "https://mainnet.infura.io/v3/".concat(import.meta.env.VITE_INFURA_API_KEY), + apiUrl: "https://api-1.snapshotx.xyz", + explorerUrl: "https://starkscan.co", + }, + "sn-sep": { + name: "Starknet (Sepolia)", + chainId: starknet_1.constants.StarknetChainId.SN_SEPOLIA, + baseChainId: 11155111, + baseNetworkId: "sep", + rpcUrl: "https://starknet-sepolia.infura.io/v3/".concat(import.meta.env.VITE_INFURA_API_KEY), + ethRpcUrl: "https://sepolia.infura.io/v3/".concat(import.meta.env.VITE_INFURA_API_KEY), + apiUrl: (_a = import.meta.env.VITE_STARKNET_SEPOLIA_API) !== null && _a !== void 0 ? _a : "https://testnet-api-1.snapshotx.xyz", + explorerUrl: "https://sepolia.starkscan.co", + }, +}; +function createStarknetNetwork(networkId) { + var _this = this; + var metadata = exports.METADATA[networkId]; + if (!metadata) + throw new Error("Unsupported network ".concat(networkId)); + var name = metadata.name, chainId = metadata.chainId, baseChainId = metadata.baseChainId, baseNetworkId = metadata.baseNetworkId, rpcUrl = metadata.rpcUrl, ethRpcUrl = metadata.ethRpcUrl, apiUrl = metadata.apiUrl, explorerUrl = metadata.explorerUrl; + var provider = (0, provider_1.createProvider)(rpcUrl); + var api = (0, common_1.createApi)(apiUrl, networkId); + var helpers = { + waitForTransaction: function (txId) { + var retries = 0; + return new Promise(function (resolve, reject) { + var timer = setInterval(function () { return __awaiter(_this, void 0, void 0, function () { + var tx, e_1, successStates; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, provider.getTransactionReceipt(txId)]; + case 1: + tx = _a.sent(); + return [3 /*break*/, 3]; + case 2: + e_1 = _a.sent(); + if (retries > 20) { + clearInterval(timer); + reject(); + } + retries++; + return [2 /*return*/]; + case 3: + successStates = [ + starknet_1.TransactionFinalityStatus.ACCEPTED_ON_L1, + starknet_1.TransactionFinalityStatus.ACCEPTED_ON_L2, + ]; + if (successStates.includes(tx.finality_status)) { + clearInterval(timer); + resolve(tx); + } + if (tx.execution_status === starknet_1.TransactionExecutionStatus.REVERTED) { + clearInterval(timer); + reject(tx); + } + return [2 /*return*/]; + } + }); + }); }, 2000); + }); + }, + getExplorerUrl: function (id, type) { + var dataType = "tx"; + if (type === "token") + dataType = "token"; + else if (["address", "contract", "strategy"].includes(type)) + dataType = "contract"; + return "".concat(explorerUrl, "/").concat(dataType, "/").concat(id); + }, + }; + return { + name: name, + avatar: "ipfs://bafkreihbjafyh7eud7r6e5743esaamifcttsvbspfwcrfoc5ykodjdi67m", + currentUnit: "second", + chainId: chainId, + baseChainId: baseChainId, + currentChainId: baseChainId, + baseNetworkId: baseNetworkId, + supportsSimulation: true, + managerConnectors: constants_1.STARKNET_CONNECTORS, + //@ts-expect-error are extra helpers needed? + actions: (0, actions_1.createActions)(networkId, provider, helpers, { + l1ChainId: baseChainId, + ethUrl: ethRpcUrl, + }), + api: api, + //@ts-expect-error are extra helpers needed? + helpers: helpers, + }; +} diff --git a/apps/frontinus-house/src/lib/network/starknet/provider.js b/apps/frontinus-house/src/lib/network/starknet/provider.js new file mode 100644 index 00000000..fefd17ac --- /dev/null +++ b/apps/frontinus-house/src/lib/network/starknet/provider.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createProvider = createProvider; +var starknet_1 = require("starknet"); +function createProvider(nodeUrl) { + return new starknet_1.RpcProvider({ + nodeUrl: nodeUrl + }); +} diff --git a/apps/frontinus-house/src/lib/network/types.js b/apps/frontinus-house/src/lib/network/types.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/apps/frontinus-house/src/lib/network/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/apps/frontinus-house/src/lib/provider.js b/apps/frontinus-house/src/lib/provider.js new file mode 100644 index 00000000..db128e1c --- /dev/null +++ b/apps/frontinus-house/src/lib/provider.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getProvider = getProvider; +var providers_1 = require("@ethersproject/providers"); +var providers = {}; +function getProvider(networkId) { + var url = "https://rpc.snapshotx.xyz/".concat(networkId); + var provider = providers[networkId]; + if (!provider) { + provider = new providers_1.StaticJsonRpcProvider({ url: url, timeout: 25000 }, networkId); + providers[networkId] = provider; + } + return provider; +} diff --git a/apps/frontinus-house/src/lib/stamp.js b/apps/frontinus-house/src/lib/stamp.js new file mode 100644 index 00000000..41862b72 --- /dev/null +++ b/apps/frontinus-house/src/lib/stamp.js @@ -0,0 +1,96 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getNames = getNames; +var utils_1 = require("./utils"); +var resolvedAddresses = new Map(); +function getNames(addresses) { + return __awaiter(this, void 0, void 0, function () { + var inputMapping, resolvedAddressesKeys_1, unresolvedAddresses, data_1, res, entries, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 4, , 5]); + inputMapping = Object.fromEntries(addresses.map(function (address) { return [address, (0, utils_1.formatAddress)(address)]; })); + resolvedAddressesKeys_1 = Array.from(resolvedAddresses.keys()); + unresolvedAddresses = Object.values(inputMapping).filter(function (address) { return !resolvedAddressesKeys_1.includes(address); }); + data_1 = []; + if (!(unresolvedAddresses.length > 0)) return [3 /*break*/, 3]; + return [4 /*yield*/, fetch("https://stamp.fyi", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + method: "lookup_addresses", + params: unresolvedAddresses, + }), + })]; + case 1: + res = _a.sent(); + return [4 /*yield*/, res.json()]; + case 2: + data_1 = (_a.sent()).result; + unresolvedAddresses.forEach(function (formatted) { + //@ts-expect-error + resolvedAddresses.set(formatted, data_1[formatted]); + }); + _a.label = 3; + case 3: + entries = Object.entries(inputMapping) + .map(function (_a) { + var address = _a[0], formatted = _a[1]; + return [ + address, + resolvedAddresses.get(formatted) || null, + ]; + }) + .filter(function (_a) { + var name = _a[1]; + return name; + }); + return [2 /*return*/, Object.fromEntries(entries)]; + case 4: + e_1 = _a.sent(); + console.error("Failed to resolve names", e_1); + return [2 /*return*/, {}]; + case 5: return [2 /*return*/]; + } + }); + }); +} diff --git a/apps/frontinus-house/src/lib/transactions.js b/apps/frontinus-house/src/lib/transactions.js new file mode 100644 index 00000000..c1c48cf4 --- /dev/null +++ b/apps/frontinus-house/src/lib/transactions.js @@ -0,0 +1,150 @@ +"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); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.convertToMetaTransactions = convertToMetaTransactions; +/* +export async function createSendTokenTransaction({ + token, + form +}: { + token: Token; + form: any; +}): Promise { + const baseAmount = parseUnits(form.amount.toString(), token.decimals); + + const isEth = token.contractAddress === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'; + + let recipientAddress = form.to; + const resolvedTo = await resolver.resolveName(form.to); + if (resolvedTo?.address) recipientAddress = resolvedTo.address; + + let data = '0x'; + if (!isEth) { + const iface = new Interface(abis.erc20); + data = iface.encodeFunctionData('transfer', [recipientAddress, baseAmount]); + } + + return { + _type: 'sendToken', + _form: { + recipient: form.to, + token: { + name: token.name, + decimals: token.decimals, + symbol: token.symbol, + address: token.contractAddress + }, + amount: baseAmount.toString() + }, + to: isEth ? recipientAddress : token.contractAddress, + data, + value: isEth ? baseAmount.toString() : '0', + salt: getSalt() + }; +} + +export async function createSendNftTransaction({ + nft, + address, + form +}): Promise { + let data = ''; + + const baseAmount = parseUnits(form.amount.toString() || '1', 0); + + let recipientAddress = form.to; + const resolvedTo = await resolver.resolveName(form.to); + if (resolvedTo?.address) recipientAddress = resolvedTo.address; + + if (nft.type === 'erc1155') { + const iface = new Interface(abis.erc1155); + + data = iface.encodeFunctionData('safeTransferFrom', [ + address, + recipientAddress, + nft.tokenId, + baseAmount, + 0 + ]); + } else if (nft.type === 'erc721') { + const iface = new Interface(abis.erc721); + + data = iface.encodeFunctionData('safeTransferFrom', [address, recipientAddress, nft.tokenId]); + } + + return { + _type: 'sendNft', + _form: { + recipient: form.to, + amount: baseAmount.toString(), + nft: { + address: nft.contractAddress, + id: nft.tokenId, + name: nft.title, + collection: nft.collectionName + } + }, + to: nft.contractAddress, + data, + value: '0', + salt: getSalt() + }; +} + +export async function createContractCallTransaction({ form }): Promise { + const args: Record = Object.values(form.args); + + let recipientAddress = form.to; + const resolvedTo = await resolver.resolveName(form.to); + if (resolvedTo?.address) recipientAddress = resolvedTo.address; + + const iface = new Interface(form.abi); + + const methodAbi = iface.functions[form.method]; + + if (methodAbi) { + await Promise.all( + methodAbi.inputs.map(async (input, i) => { + if (input.type === 'address') { + const resolved = await resolver.resolveName(args[i]); + if (resolved?.address) args[i] = resolved.address; + } else if (input.type.endsWith('[]')) { + args[i] = args[i].split(',').map(value => value.trim()); + } + }) + ); + } + + const data = iface.encodeFunctionData(form.method, args as any); + + return { + _type: 'contractCall', + to: recipientAddress, + data, + value: iface.getFunction(form.method).payable + ? parseUnits(form.amount.toString(), 18).toString() + : '0', + salt: getSalt(), + _form: { + abi: form.abi, + recipient: form.to, + method: form.method, + args: form.args, + amount: form.amount + } + }; +} +*/ +function convertToMetaTransactions(transactions) { + return transactions.map(function (tx) { return (__assign(__assign({}, tx), { operation: 0, salt: BigInt(tx.salt) })); }); +} diff --git a/apps/frontinus-house/src/lib/utils.js b/apps/frontinus-house/src/lib/utils.js new file mode 100644 index 00000000..3ec31c9d --- /dev/null +++ b/apps/frontinus-house/src/lib/utils.js @@ -0,0 +1,191 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.shorten = shorten; +exports.shortenAddress = shortenAddress; +exports.formatAddress = formatAddress; +exports.getUrl = getUrl; +exports.getProposalId = getProposalId; +exports.verifyNetwork = verifyNetwork; +exports._rt = _rt; +var constants_1 = require("@/data/constants"); +var address_1 = require("@ethersproject/address"); +var starknet_1 = require("starknet"); +var IPFS_GATEWAY = import.meta.env.VITE_IPFS_GATEWAY || "https://cloudflare-ipfs.com"; +function shorten(str, key) { + if (!str) + return str; + var limit; + if (typeof key === "number") + limit = key; + if (key === "symbol") + limit = constants_1.MAX_SYMBOL_LENGTH; + if (key === "name") + limit = 64; + if (key === "choice") + limit = 12; + if (limit) + return str.length > limit ? "".concat(str.slice(0, limit).trim(), "...") : str; + return shortenAddress(str); +} +function shortenAddress(str) { + if (str === void 0) { str = ""; } + var formatted = formatAddress(str); + return "".concat(formatted.slice(0, 6), "...").concat(formatted.slice(formatted.length - 4)); +} +function formatAddress(address) { + if (address.length === 42) + return (0, address_1.getAddress)(address); + try { + return (0, starknet_1.validateAndParseAddress)(address); + } + catch (_a) { + return address; + } +} +function getUrl(uri) { + var ipfsGateway = "https://".concat(IPFS_GATEWAY); + if (!uri) + return null; + if (!uri.startsWith("ipfs://") && + !uri.startsWith("ipns://") && + !uri.startsWith("https://") && + !uri.startsWith("http://")) { + return "".concat(ipfsGateway, "/ipfs/").concat(uri); + } + var uriScheme = uri.split("://")[0]; + if (uriScheme === "ipfs") + return uri.replace("ipfs://", "".concat(ipfsGateway, "/ipfs/")); + if (uriScheme === "ipns") + return uri.replace("ipns://", "".concat(ipfsGateway, "/ipns/")); + return uri; +} +function getProposalId(proposal) { + var proposalId = proposal.proposal_id.toString(); + if (proposalId.startsWith("0x")) { + return "#".concat(proposalId.slice(2, 7)); + } + if ([46, 59].includes(proposalId.length)) { + return "#".concat(proposalId.slice(-5)); + } + return "#".concat(proposalId); +} +function verifyNetwork(web3Provider, chainId) { + return __awaiter(this, void 0, void 0, function () { + var network, encodedChainId, err_1, network_1, error; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!web3Provider.provider.request) + return [2 /*return*/]; + return [4 /*yield*/, web3Provider.getNetwork()]; + case 1: + network = _a.sent(); + if (network.chainId === chainId) + return [2 /*return*/]; + encodedChainId = "0x".concat(chainId.toString(16)); + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 6]); + return [4 /*yield*/, web3Provider.provider.request({ + method: "wallet_switchEthereumChain", + params: [{ chainId: encodedChainId }], + })]; + case 3: + _a.sent(); + return [3 /*break*/, 6]; + case 4: + err_1 = _a.sent(); + //@ts-expect-error + if (err_1.code !== 4902) + throw new Error(err_1.message); + return [4 /*yield*/, web3Provider.getNetwork()]; + case 5: + network_1 = _a.sent(); + if (network_1.chainId !== chainId) { + error = new Error("User rejected network change after it being added"); + error.code = 4001; + throw error; + } + return [3 /*break*/, 6]; + case 6: return [2 /*return*/]; + } + }); + }); +} +function _rt(date) { + var seconds = Math.floor(new Date().getTime() / 1000 - date); + var years = Math.floor(seconds / 31536000); + var months = Math.floor(seconds / 2592000); + var days = Math.floor(seconds / 86400); + if (days > 548) { + return years + " years ago"; + } + if (days >= 320 && days <= 547) { + return "a year ago"; + } + if (days >= 45 && days <= 319) { + return months + " months ago"; + } + if (days >= 26 && days <= 45) { + return "a month ago"; + } + var hours = Math.floor(seconds / 3600); + if (hours >= 36 && days <= 25) { + return days + " days ago"; + } + if (hours >= 22 && hours <= 35) { + return "a day ago"; + } + var minutes = Math.floor(seconds / 60); + if (minutes >= 90 && hours <= 21) { + return hours + " hours ago"; + } + if (minutes >= 45 && minutes <= 89) { + return "an hour ago"; + } + if (seconds >= 90 && minutes <= 44) { + return minutes + " minutes ago"; + } + if (seconds >= 45 && seconds <= 89) { + return "a minute ago"; + } + if (seconds >= 0 && seconds <= 45) { + return "a few seconds ago"; + } +} diff --git a/apps/frontinus-house/src/main.jsx b/apps/frontinus-house/src/main.jsx new file mode 100644 index 00000000..97746f03 --- /dev/null +++ b/apps/frontinus-house/src/main.jsx @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var react_1 = require("react"); +var router_1 = require("@/router"); +var client_1 = require("react-dom/client"); +var react_router_dom_1 = require("react-router-dom"); +require("./App.css"); +client_1.default.createRoot(document.getElementById("root")).render( + + ); diff --git a/apps/frontinus-house/src/pages/delegates/index.jsx b/apps/frontinus-house/src/pages/delegates/index.jsx new file mode 100644 index 00000000..1ac4f4af --- /dev/null +++ b/apps/frontinus-house/src/pages/delegates/index.jsx @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Delegates; +var react_1 = require("react"); +var layout_1 = require("@/components/layout"); +var space_provider_1 = require("@/components/space-provider"); +var space_delegates_1 = require("./space-delegates"); +function Delegates() { + var space = (0, space_provider_1.useSpace)().space; + var _a = (0, react_1.useState)(0), activeDelegationId = _a[0], setActiveDelegationId = _a[1]; + var delegateData = space === null || space === void 0 ? void 0 : space.delegations[activeDelegationId]; + return ( + +
+

Delegates

+
+ {delegateData && } +
+
); +} diff --git a/apps/frontinus-house/src/pages/delegates/space-delegates.jsx b/apps/frontinus-house/src/pages/delegates/space-delegates.jsx new file mode 100644 index 00000000..eea95641 --- /dev/null +++ b/apps/frontinus-house/src/pages/delegates/space-delegates.jsx @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SpaceDelegates = void 0; +var react_1 = require("react"); +var use_delegates_1 = require("@/hooks/use-delegates"); +var utils_1 = require("@/lib/utils"); +var SpaceDelegates = function (_a) { + var delegation = _a.delegation; + var _b = (0, use_delegates_1.useDelegates)(delegation.apiUrl), loading = _b.loading, loadingMore = _b.loadingMore, loaded = _b.loaded, failed = _b.failed, hasMore = _b.hasMore, delegates = _b.delegates, fetch = _b.fetch, fetchMore = _b.fetchMore, reset = _b.reset; + (0, react_1.useEffect)(function () { + fetch(); + }, []); + return ( + + + + + + + + + + + + + + {delegates.map(function (delegate, i) { + return ( + + + + ); + })} + +
+ Delegatee + + + + +
+ {/* */} + + +

+ {delegate.tokenHoldersRepresentedAmount} +

+
+ {delegate.delegatorsPercentage.toFixed(3)}% +
+
+

+ {parseInt(delegate.delegatedVotes)} +

+
+ {delegate.votesPercentage.toFixed(3)}% +
+
); +}; +exports.SpaceDelegates = SpaceDelegates; diff --git a/apps/frontinus-house/src/pages/error/general-error.jsx b/apps/frontinus-house/src/pages/error/general-error.jsx new file mode 100644 index 00000000..697e87d2 --- /dev/null +++ b/apps/frontinus-house/src/pages/error/general-error.jsx @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = GeneralError; +var react_router_dom_1 = require("react-router-dom"); +var ui_1 = require("@realms-world/ui"); +var utils_1 = require("@realms-world/utils"); +function GeneralError(_a) { + var className = _a.className, _b = _a.minimal, minimal = _b === void 0 ? false : _b; + var navigate = (0, react_router_dom_1.useNavigate)(); + return (
+
+ {!minimal && (

500

)} + Oops! Something went wrong {":')"} +

+ We apologize for the inconvenience.
Please try again later. +

+ {!minimal && (
+ + Go Back + + Back to Home +
)} +
+
); +} diff --git a/apps/frontinus-house/src/pages/error/not-found-error.jsx b/apps/frontinus-house/src/pages/error/not-found-error.jsx new file mode 100644 index 00000000..0be88a58 --- /dev/null +++ b/apps/frontinus-house/src/pages/error/not-found-error.jsx @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = NotFoundError; +var react_router_dom_1 = require("react-router-dom"); +var ui_1 = require("@realms-world/ui"); +function NotFoundError() { + var navigate = (0, react_router_dom_1.useNavigate)(); + return (
+
+

404

+ Oops! Page Not Found! +

+ It seems like the page you're looking for
+ does not exist or might have been removed. +

+
+ + Go Back + + Back to Home +
+
+
); +} diff --git a/apps/frontinus-house/src/pages/overview/index.jsx b/apps/frontinus-house/src/pages/overview/index.jsx new file mode 100644 index 00000000..e00437d9 --- /dev/null +++ b/apps/frontinus-house/src/pages/overview/index.jsx @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Overview; +function Overview() { + return (

Test

); +} diff --git a/apps/frontinus-house/src/pages/proposals/[id]/index.jsx b/apps/frontinus-house/src/pages/proposals/[id]/index.jsx new file mode 100644 index 00000000..06b0b5ad --- /dev/null +++ b/apps/frontinus-house/src/pages/proposals/[id]/index.jsx @@ -0,0 +1,73 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Proposal; +var react_1 = require("react"); +var layout_1 = require("@/components/layout"); +var network_1 = require("@/lib/network"); +var overview_1 = require("./overview"); +function Proposal() { + var _this = this; + var _a = (0, react_1.useState)(null), proposal = _a[0], setProposal = _a[1]; + console.log("got here"); + (0, react_1.useEffect)(function () { + var fetchProposals = function () { return __awaiter(_this, void 0, void 0, function () { + var proposalsData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, network_1.getNetwork)("sn-sep").api.loadProposal("0x0011c8d7674bb371708933d29c5e2a4ea31a6535809950b863851373f1afc112", 1, 0)]; + case 1: + proposalsData = _a.sent(); + setProposal(proposalsData); + return [2 /*return*/]; + } + }); + }); }; + fetchProposals(); + }, []); + console.log(proposal); + return ( + +
+

Proposal

+
+
+ {proposal ? : "Loading"} +
+
); +} diff --git a/apps/frontinus-house/src/pages/proposals/[id]/overview.jsx b/apps/frontinus-house/src/pages/proposals/[id]/overview.jsx new file mode 100644 index 00000000..b4880969 --- /dev/null +++ b/apps/frontinus-house/src/pages/proposals/[id]/overview.jsx @@ -0,0 +1,217 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Overview; +var Markdown_1 = require("@/components/Markdown"); +var utils_1 = require("@/lib/utils"); +var react_router_dom_1 = require("react-router-dom"); +var button_1 = require("@realms-world/ui/components/ui/button"); +var dropdown_menu_1 = require("@realms-world/ui/components/ui/dropdown-menu"); +function Overview(_a) { + var proposal = _a.proposal; + var location = (0, react_router_dom_1.useLocation)(); + var currentUrl = "".concat(window.location.origin, "/#").concat(location.pathname); + var shareMsg = encodeURIComponent("".concat(proposal.space.name, ": ").concat(proposal.title, " ").concat(currentUrl)); + return (
+

+ {proposal.title || "Proposal #".concat(proposal.proposal_id)} + {(0, utils_1.getProposalId)(proposal)} +

+ + {/**/} + +
+ + {/**/} +
+ {proposal.author.name || (0, utils_1.shortenAddress)(proposal.author.id)} + + In + + {proposal.space.name} + + · {(0, utils_1._rt)(proposal.created)} + +
+
+
+ {/* + + + + + */} + + + + + {/**/} + Share + + + + + + {/**/} + Share on X + + + + + {/* */} + Share on Lens + + + + + {/**/} + Share on Farcaster + + + + + {/* + + + + + + + + {cancellable &&()} + + + + + + View metadata + + + + */} +
+
+ {/*
+

+ + AI summary +

+
{ aiSummaryContent }
+
+ + AI can be inaccurate or misleading. +
+
*/} + {proposal.body && (
+ +
)} + {/*
+

+ + Discussion +

+ + + +
+
+

+ + Execution +

+
+ +
+
+
+

+ + Actions +

+
+ +
+
+ */} +
); +} diff --git a/apps/frontinus-house/src/pages/proposals/index.jsx b/apps/frontinus-house/src/pages/proposals/index.jsx new file mode 100644 index 00000000..0fc5703e --- /dev/null +++ b/apps/frontinus-house/src/pages/proposals/index.jsx @@ -0,0 +1,100 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Proposals; +var react_1 = require("react"); +var layout_1 = require("@/components/layout"); +var network_1 = require("@/lib/network"); +var utils_1 = require("@/lib/utils"); +var react_router_dom_1 = require("react-router-dom"); +function Proposals() { + var _this = this; + var _a = (0, react_1.useState)(), proposals = _a[0], setProposals = _a[1]; + console.log("got here"); + (0, react_1.useEffect)(function () { + var fetchProposals = function () { return __awaiter(_this, void 0, void 0, function () { + var proposalsData; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, network_1.getNetwork)("sn-sep").api.loadProposals(["0x0011c8d7674bb371708933d29c5e2a4ea31a6535809950b863851373f1afc112"], { + limit: 20, + }, 0, "any")]; + case 1: + proposalsData = _a.sent(); + setProposals(proposalsData); + return [2 /*return*/]; + } + }); + }); }; + fetchProposals(); + }, []); + console.log(proposals); + return ( + +
+

Proposals

+
+
+ {proposals + ? proposals.map(function (proposal) { + var _a; + return (
+ +
+
+
+
+

+ {(_a = proposal.title) !== null && _a !== void 0 ? _a : "Proposal #".concat(proposal.id)} +

+
+
+
+ {(0, utils_1.getProposalId)(proposal)} by{" "} + {proposal.author.name || (0, utils_1.shorten)(proposal.author.id)} +
+ {proposal.vote_count} votes +
+
+
+
); + }) + : "Loading"} +
+
); +} diff --git a/apps/frontinus-house/src/pages/rounds/index.jsx b/apps/frontinus-house/src/pages/rounds/index.jsx new file mode 100644 index 00000000..bda11287 --- /dev/null +++ b/apps/frontinus-house/src/pages/rounds/index.jsx @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Rounds; +function Rounds() { + return (

Rounds

); +} diff --git a/apps/frontinus-house/src/router.jsx b/apps/frontinus-house/src/router.jsx new file mode 100644 index 00000000..31baaaa8 --- /dev/null +++ b/apps/frontinus-house/src/router.jsx @@ -0,0 +1,145 @@ +"use strict"; +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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var general_error_1 = require("@/pages/error/general-error"); +var not_found_error_1 = require("@/pages/error/not-found-error"); +var react_router_dom_1 = require("react-router-dom"); +//import MaintenanceError from './pages/errors/maintenance-error' +var router = (0, react_router_dom_1.createBrowserRouter)([ + // Main routes + { + path: "/", + lazy: function () { return __awaiter(void 0, void 0, void 0, function () { + var AppShell; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, Promise.resolve().then(function () { return require("@/components/app-shell"); })]; + case 1: + AppShell = _a.sent(); + return [2 /*return*/, { Component: AppShell.default }]; + } + }); + }); }, + errorElement: , + children: [ + { + index: true, + lazy: function () { return __awaiter(void 0, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = {}; + return [4 /*yield*/, Promise.resolve().then(function () { return require("@/pages/overview"); })]; + case 1: return [2 /*return*/, (_a.Component = (_b.sent()).default, + _a)]; + } + }); + }); }, + }, + { + path: "proposals", + lazy: function () { return __awaiter(void 0, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = {}; + return [4 /*yield*/, Promise.resolve().then(function () { return require("@/pages/proposals"); })]; + case 1: return [2 /*return*/, (_a.Component = (_b.sent()).default, + _a)]; + } + }); + }); }, + children: [], + }, + { + path: "proposals/:id", + lazy: function () { return __awaiter(void 0, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = {}; + return [4 /*yield*/, Promise.resolve().then(function () { return require("@/pages/proposals/[id]"); })]; + case 1: return [2 /*return*/, (_a.Component = (_b.sent()).default, + _a)]; + } + }); + }); }, + }, + { + path: "rounds", + lazy: function () { return __awaiter(void 0, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = {}; + return [4 /*yield*/, Promise.resolve().then(function () { return require("@/pages/rounds"); })]; + case 1: return [2 /*return*/, (_a.Component = (_b.sent()).default, + _a)]; + } + }); + }); }, + }, + { + path: "delegates", + lazy: function () { return __awaiter(void 0, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = {}; + return [4 /*yield*/, Promise.resolve().then(function () { return require("@/pages/delegates"); })]; + case 1: return [2 /*return*/, (_a.Component = (_b.sent()).default, + _a)]; + } + }); + }); }, + }, + ], + }, + // Error routes + { path: "/500", Component: general_error_1.default }, + { path: "/404", Component: not_found_error_1.default }, + //{ path: '/503', Component: MaintenanceError }, + // Fallback 404 route + { path: "*", Component: not_found_error_1.default }, +]); +exports.default = router; diff --git a/apps/frontinus-house/src/types.js b/apps/frontinus-house/src/types.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/apps/frontinus-house/src/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/apps/frontinus-house/tailwind.config.js b/apps/frontinus-house/tailwind.config.js index 3c55cc63..db054ecc 100644 --- a/apps/frontinus-house/tailwind.config.js +++ b/apps/frontinus-house/tailwind.config.js @@ -1,2 +1,2 @@ /** @type {import('tailwindcss').Config} */ -module.exports = require("@realms-world/tailwind-config"); +module.exports = require("@realms-world/tailwind-config/web"); diff --git a/apps/frontinus/package.json b/apps/frontinus/package.json index 7fcbd7e1..a5092ab5 100644 --- a/apps/frontinus/package.json +++ b/apps/frontinus/package.json @@ -15,11 +15,11 @@ "@parcel/watcher": "^2.4.1", "@realms-world/tailwind-config": "workspace:*", "@realms-world/tsconfig": "workspace:*", - "@tanstack/router-plugin": "^1.64.0", + "@tanstack/router-plugin": "^1.74.2", "@types/react": "^18.3.11", - "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.2", - "vite": "^5.4.8", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.9", "vite-tsconfig-paths": "^5.0.1" }, "dependencies": { @@ -27,24 +27,24 @@ "@realms-world/styles": "workspace:*", "@realms-world/ui": "workspace:*", "@realms-world/utils": "workspace:*", - "@starknet-react/chains": "^3.0.0", - "@starknet-react/core": "^3.0.1", - "@tanstack/react-query": "^5.59.9", - "@tanstack/react-query-devtools": "^5.59.9", - "@tanstack/react-router": "^1.64.0", - "@tanstack/react-router-with-query": "^1.64.0", - "@tanstack/router-devtools": "^1.64.0", - "@tanstack/start": "^1.64.0", + "@starknet-react/chains": "^3.0.2", + "@starknet-react/core": "^3.0.3", + "@tanstack/react-query": "^5.59.15", + "@tanstack/react-query-devtools": "^5.59.15", + "@tanstack/react-router": "^1.74.4", + "@tanstack/react-router-with-query": "^1.74.4", + "@tanstack/router-devtools": "^1.74.4", + "@tanstack/start": "^1.74.4", "date-fns": "^4.1.0", - "get-starknet-core": "^3.3.3", + "get-starknet-core": "^3.3.4", "graphql": "^16.9.0", "graphql-request": "^7.1.0", - "lucide-react": "^0.451.0", + "lucide-react": "^0.453.0", "react": "catalog:react18", "react-dom": "catalog:react18", "starknet": "^6.11.0", - "starknetkit": "^2.3.2", - "tailwindcss": "3.4.13", + "starknetkit": "^2.3.3", + "tailwindcss": "catalog:", "vinxi": "0.4.3" } } diff --git a/apps/frontinus/tailwind.config.js b/apps/frontinus/tailwind.config.js index 3c55cc63..db054ecc 100644 --- a/apps/frontinus/tailwind.config.js +++ b/apps/frontinus/tailwind.config.js @@ -1,2 +1,2 @@ /** @type {import('tailwindcss').Config} */ -module.exports = require("@realms-world/tailwind-config"); +module.exports = require("@realms-world/tailwind-config/web"); diff --git a/apps/nextjs/content/collections/banners.mdoc b/apps/nextjs/content/collections/banners.mdoc new file mode 100644 index 00000000..e46ee5b1 --- /dev/null +++ b/apps/nextjs/content/collections/banners.mdoc @@ -0,0 +1,5 @@ +--- +title: Pixel Banners (for Adventurers) +links: {} +games: [] +--- diff --git a/apps/nextjs/content/collections/beasts.mdoc b/apps/nextjs/content/collections/beasts.mdoc new file mode 100644 index 00000000..71b6be4a --- /dev/null +++ b/apps/nextjs/content/collections/beasts.mdoc @@ -0,0 +1,5 @@ +--- +title: Beasts +links: {} +games: [] +--- diff --git a/apps/nextjs/content/collections/blobert.mdoc b/apps/nextjs/content/collections/blobert.mdoc new file mode 100644 index 00000000..53e4f7ec --- /dev/null +++ b/apps/nextjs/content/collections/blobert.mdoc @@ -0,0 +1,5 @@ +--- +title: Blobert +links: {} +games: [] +--- diff --git a/apps/nextjs/content/collections/golden-token.mdoc b/apps/nextjs/content/collections/golden-token.mdoc new file mode 100644 index 00000000..0b9e703c --- /dev/null +++ b/apps/nextjs/content/collections/golden-token.mdoc @@ -0,0 +1,5 @@ +--- +title: Golden Token +links: {} +games: [] +--- diff --git a/apps/nextjs/content/collections/realms.mdoc b/apps/nextjs/content/collections/realms.mdoc new file mode 100644 index 00000000..685c4273 --- /dev/null +++ b/apps/nextjs/content/collections/realms.mdoc @@ -0,0 +1,6 @@ +--- +title: Realms +links: {} +games: + - realms-eternum +--- diff --git a/apps/nextjs/env.ts b/apps/nextjs/env.ts index f37134df..6bf9915a 100644 --- a/apps/nextjs/env.ts +++ b/apps/nextjs/env.ts @@ -21,7 +21,6 @@ export const env = createEnv({ */ server: { DATABASE_URL: z.string().url(), - INNGEST_EVENT_KEY: z.string().optional(), }, /** diff --git a/apps/nextjs/keystatic.config.ts b/apps/nextjs/keystatic.config.ts index 6d9307fd..e689183c 100644 --- a/apps/nextjs/keystatic.config.ts +++ b/apps/nextjs/keystatic.config.ts @@ -1,13 +1,20 @@ import { collection, config, fields } from "@keystatic/core"; import { env } from "env"; -export default config({ - storage: { - kind: "github", - repo: `${env.NEXT_PUBLIC_GITHUB_REPO_OWNER}/${env.NEXT_PUBLIC_GITHUB_REPO_NAME}`, - pathPrefix: "apps/nextjs", - }, +function storage() { + if (env.NODE_ENV == "development") { + return { kind: "local" } as const; + } else { + return { + kind: "github", + repo: `${env.NEXT_PUBLIC_GITHUB_REPO_OWNER}/${env.NEXT_PUBLIC_GITHUB_REPO_NAME}`, + pathPrefix: "apps/nextjs", + } as const; + } +} +export default config({ + storage: storage(), ui: { brand: { name: "Realms.World" }, }, @@ -153,7 +160,7 @@ export default config({ }), { label: "Games", - itemLabel: (props) => props.value, + itemLabel: (props) => props.value ?? "", }, ), }, @@ -189,5 +196,43 @@ export default config({ }), }, }), + collections: collection({ + label: "Collections", + slugField: "title", + path: "content/collections/*", + format: { contentField: "content" }, + columns: ["title", "description"], + schema: { + title: fields.slug({ + name: { label: "Title" }, + }), + description: fields.text({ label: "Description" }), + content: fields.markdoc({ label: "Content" }), + links: fields.object( + { + homepage: fields.url({ label: "Website" }), + discord: fields.url({ label: "Discord" }), + twitter: fields.text({ label: "Twitter" }), + telegram: fields.url({ label: "Telegram" }), + github: fields.url({ label: "Github" }), + }, + { label: "Links" }, + ), + logo: fields.image({ + label: "Logo", + directory: "public/content/studios", + }), + games: fields.array( + fields.relationship({ + label: "Games", + collection: "games", + }), + { + label: "Games", + itemLabel: (props) => props.value, + }, + ), + }, + }), }, }); diff --git a/apps/nextjs/next.config.js b/apps/nextjs/next.config.ts similarity index 87% rename from apps/nextjs/next.config.js rename to apps/nextjs/next.config.ts index e807b038..660a96c5 100644 --- a/apps/nextjs/next.config.js +++ b/apps/nextjs/next.config.ts @@ -1,14 +1,16 @@ import { fileURLToPath } from "url"; +import type { NextConfig } from "next"; import MillionLint from "@million/lint"; import createMDX from "@next/mdx"; -import createJiti from "jiti"; +import { env } from "env"; +import { createJiti } from "jiti"; -// Import env files to validate at build time. Use jiti so we can load .ts files in here. -createJiti(fileURLToPath(import.meta.url))("./env"); +/*// Import env files to validate at build time. Use jiti so we can load .ts files in here. +await createJiti(fileURLToPath(import.meta.url)).import("./env");*/ /** @type {import("next").NextConfig} */ -const config = { +const nextConfig: NextConfig = { reactStrictMode: true, /** Enables hot reloading for local packages without a build step */ transpilePackages: [ @@ -112,9 +114,8 @@ const withMDX = createMDX({ extension: /\.mdx?$/, }); -const enhancedConfig = - !process.env.NODE_ENV === "production" - ? MillionLint.next({ rsc: true, auto: { rsc: true } })(withMDX(config)) - : withMDX(config); +const enhancedConfig = !(env.NODE_ENV === "production") + ? MillionLint.next({ rsc: true })(withMDX(nextConfig)) + : withMDX(nextConfig); -export default enhancedConfig; +export default withMDX(nextConfig); diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json index 7e5122b0..5f8379c1 100644 --- a/apps/nextjs/package.json +++ b/apps/nextjs/package.json @@ -16,6 +16,7 @@ "dependencies": { "@ark-project/react": "1.1.2", "@avnu/avnu-sdk": "^2.1.1", + "@cartridge/connector": "^0.4.0", "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", "@keystatic/core": "^0.5.36", @@ -26,8 +27,7 @@ "@million/lint": "1.0.0-rc.75", "@mui/material": "^5.15.15", "@mui/styles": "^5.15.15", - "@next/mdx": "^14.2.5", - "@cartridge/connector": "^0.3.46", + "@next/mdx": "^14.2.15", "@rainbow-me/rainbowkit": "^2", "@realms-world/api": "workspace:*", "@realms-world/auth": "workspace:*", @@ -38,49 +38,49 @@ "@realms-world/ui": "workspace:*", "@realms-world/utils": "workspace:*", "@reservoir0x/reservoir-kit-ui": "^2.5.16", - "@starknet-react/chains": "^3.0.0", - "@starknet-react/core": "^3.0.1", + "@starknet-react/chains": "^3.0.2", + "@starknet-react/core": "^3.0.3", "@starkware-industries/commons-js-enums": "^1.2.0", "@starkware-industries/commons-js-utils": "^1.2.2", "@svgr/webpack": "^8.1.0", "@t3-oss/env-nextjs": "^0.11.1", - "@tanstack/react-query": "5.59.0", + "@tanstack/react-query": "5.59.15", "@trpc/client": "11.0.0-rc.477", "@trpc/react-query": "11.0.0-rc.477", "@trpc/server": "11.0.0-rc.477", "@vercel/analytics": "^1.3.1", + "blockies-ts": "^1.0.0", "class-variance-authority": "^0.7.0", "cmdk": "^1.0.0", "date-fns": "3.6.0", "embla-carousel-autoplay": "8.3.0", "embla-carousel-react": "8.3.0", - "eslint-config-next": "^15.0.0-rc.0", - "framer-motion": "^11.5.4", + "eslint-config-next": "^15.0.0-rc.1", + "framer-motion": "^11.11.9", "frames.js": "^0.15.1", "gray-matter": "^4.0.3", - "inngest": "^3.19.0", "keccak256": "^1.0.6", "lodash": "4.17.21", "lucide-react": "^0.441.0", "merkletreejs": "^0.3.11", - "next": "^15.0.0-rc.0", - "nuqs": "^1.19.3", + "next": "^15.0.0-rc.1", + "nuqs": "^1.20.0", "react": "catalog:react19", "react-dom": "catalog:react19", "react-is": "catalog:react19", - "react-virtuoso": "^4.10.4", - "recharts": "^2.13.0-alpha.4", + "react-virtuoso": "^4.12.0", + "recharts": "^2.13.0", "remark": "^15.0.1", "remark-html": "^16.0.1", "server-only": "0.0.1", "siws": "workspace:*", "starknet": "6.11.0", - "starknetkit": "^2.3.2", + "starknetkit": "^2.3.3", "superjson": "2.2.1", - "viem": "^2.21.9", - "wagmi": "^2.12.12", + "viem": "^2.21.27", + "wagmi": "^2.12.19", "zod": "catalog:", - "zustand": "5.0.0-rc.2" + "zustand": "5.0.0" }, "devDependencies": { "@realms-world/eslint-config": "workspace:*", @@ -88,14 +88,14 @@ "@realms-world/tailwind-config": "workspace:*", "@realms-world/tsconfig": "workspace:*", "@types/mdx": "^2.0.13", - "@types/node": "^22.5.5", + "@types/node": "^22.7.5", "@types/react": "catalog:react19", "@types/react-dom": "catalog:react19", "dotenv-cli": "^7.4.2", "eslint": "catalog:", - "jiti": "^1.21.6", + "jiti": "^2.3.3", "prettier": "catalog:", - "tailwindcss": "3.4.13", + "tailwindcss": "catalog:", "typescript": "catalog:" }, "prettier": "@realms-world/prettier-config" diff --git a/apps/nextjs/public/collections/realms/resources/1.png b/apps/nextjs/public/collections/realms/resources/1.png new file mode 100644 index 00000000..7c8b3590 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/1.png differ diff --git a/apps/nextjs/public/collections/realms/resources/10.png b/apps/nextjs/public/collections/realms/resources/10.png new file mode 100644 index 00000000..bb6d56ae Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/10.png differ diff --git a/apps/nextjs/public/collections/realms/resources/11.png b/apps/nextjs/public/collections/realms/resources/11.png new file mode 100644 index 00000000..1cb79097 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/11.png differ diff --git a/apps/nextjs/public/collections/realms/resources/12.png b/apps/nextjs/public/collections/realms/resources/12.png new file mode 100644 index 00000000..f1a596f6 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/12.png differ diff --git a/apps/nextjs/public/collections/realms/resources/13.png b/apps/nextjs/public/collections/realms/resources/13.png new file mode 100644 index 00000000..3df9c0d3 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/13.png differ diff --git a/apps/nextjs/public/collections/realms/resources/14.png b/apps/nextjs/public/collections/realms/resources/14.png new file mode 100644 index 00000000..0ca47a48 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/14.png differ diff --git a/apps/nextjs/public/collections/realms/resources/15.png b/apps/nextjs/public/collections/realms/resources/15.png new file mode 100644 index 00000000..aa46c53e Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/15.png differ diff --git a/apps/nextjs/public/collections/realms/resources/16.png b/apps/nextjs/public/collections/realms/resources/16.png new file mode 100644 index 00000000..a268ce88 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/16.png differ diff --git a/apps/nextjs/public/collections/realms/resources/17.png b/apps/nextjs/public/collections/realms/resources/17.png new file mode 100644 index 00000000..78b1701f Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/17.png differ diff --git a/apps/nextjs/public/collections/realms/resources/18.png b/apps/nextjs/public/collections/realms/resources/18.png new file mode 100644 index 00000000..dc32ad44 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/18.png differ diff --git a/apps/nextjs/public/collections/realms/resources/19.png b/apps/nextjs/public/collections/realms/resources/19.png new file mode 100644 index 00000000..e8c4d778 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/19.png differ diff --git a/apps/nextjs/public/collections/realms/resources/2.png b/apps/nextjs/public/collections/realms/resources/2.png new file mode 100644 index 00000000..2152434a Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/2.png differ diff --git a/apps/nextjs/public/collections/realms/resources/20.png b/apps/nextjs/public/collections/realms/resources/20.png new file mode 100644 index 00000000..b2cf70b1 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/20.png differ diff --git a/apps/nextjs/public/collections/realms/resources/21.png b/apps/nextjs/public/collections/realms/resources/21.png new file mode 100644 index 00000000..a92794e0 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/21.png differ diff --git a/apps/nextjs/public/collections/realms/resources/22.png b/apps/nextjs/public/collections/realms/resources/22.png new file mode 100644 index 00000000..74d73987 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/22.png differ diff --git a/apps/nextjs/public/collections/realms/resources/254.png b/apps/nextjs/public/collections/realms/resources/254.png new file mode 100644 index 00000000..10c51b23 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/254.png differ diff --git a/apps/nextjs/public/collections/realms/resources/255.png b/apps/nextjs/public/collections/realms/resources/255.png new file mode 100644 index 00000000..c4c06848 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/255.png differ diff --git a/apps/nextjs/public/collections/realms/resources/29.png b/apps/nextjs/public/collections/realms/resources/29.png new file mode 100644 index 00000000..06135412 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/29.png differ diff --git a/apps/nextjs/public/collections/realms/resources/3.png b/apps/nextjs/public/collections/realms/resources/3.png new file mode 100644 index 00000000..537940af Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/3.png differ diff --git a/apps/nextjs/public/collections/realms/resources/4.png b/apps/nextjs/public/collections/realms/resources/4.png new file mode 100644 index 00000000..bd657360 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/4.png differ diff --git a/apps/nextjs/public/collections/realms/resources/5.png b/apps/nextjs/public/collections/realms/resources/5.png new file mode 100644 index 00000000..113f453d Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/5.png differ diff --git a/apps/nextjs/public/collections/realms/resources/6.png b/apps/nextjs/public/collections/realms/resources/6.png new file mode 100644 index 00000000..d8f0281a Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/6.png differ diff --git a/apps/nextjs/public/collections/realms/resources/7.png b/apps/nextjs/public/collections/realms/resources/7.png new file mode 100644 index 00000000..14bcaf2c Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/7.png differ diff --git a/apps/nextjs/public/collections/realms/resources/8.png b/apps/nextjs/public/collections/realms/resources/8.png new file mode 100644 index 00000000..5180be72 Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/8.png differ diff --git a/apps/nextjs/public/collections/realms/resources/9.png b/apps/nextjs/public/collections/realms/resources/9.png new file mode 100644 index 00000000..51e5a0ab Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/9.png differ diff --git a/apps/nextjs/public/collections/realms/resources/coin.png b/apps/nextjs/public/collections/realms/resources/coin.png new file mode 100644 index 00000000..27fab33c Binary files /dev/null and b/apps/nextjs/public/collections/realms/resources/coin.png differ diff --git a/apps/nextjs/src/app/(app)/account/_components/StarknetAccountLogin.tsx b/apps/nextjs/src/app/(app)/account/_components/StarknetAccountLogin.tsx index bca8218b..1e6423e4 100644 --- a/apps/nextjs/src/app/(app)/account/_components/StarknetAccountLogin.tsx +++ b/apps/nextjs/src/app/(app)/account/_components/StarknetAccountLogin.tsx @@ -1,10 +1,10 @@ import { StarknetLoginButton } from "@/app/_components/wallet/StarknetLoginButton"; import { Card, - CardFooter, - CardTitle, CardContent, + CardFooter, CardHeader, + CardTitle, } from "@realms-world/ui/components/ui/card"; import { useAccount as useStarknetAccount } from "@starknet-react/core"; @@ -19,14 +19,12 @@ export const StarknetAccountLogin = () => { -

- Sign in with your wallet to access: -

    -
  • veLords
  • -
  • L2 Assets and Marketplaces
  • -
  • Delegation and Lords Rewards for Realms
  • -
-

+ Sign in with your wallet to access: +
    +
  • veLords
  • +
  • L2 Assets and Marketplaces
  • +
  • Delegation and Lords Rewards for Realms
  • +
{!isStarknetConnected && ( diff --git a/apps/nextjs/src/app/(app)/account/_components/sidebar/AccountSidebar.tsx b/apps/nextjs/src/app/(app)/account/_components/sidebar/AccountSidebar.tsx index 4a88fdd3..0251031e 100644 --- a/apps/nextjs/src/app/(app)/account/_components/sidebar/AccountSidebar.tsx +++ b/apps/nextjs/src/app/(app)/account/_components/sidebar/AccountSidebar.tsx @@ -1,10 +1,40 @@ "use client"; +import Link from "next/link"; +import LordsIcon from "@/icons/lords.svg"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@realms-world/ui/components/ui/collapsible"; +/*import { NavProjects } from "./nav-projects" +import { NavSecondary } from "./nav-secondary" +import { NavUser } from "./nav-user" +import { StorageCard } from "./storage-card" +import { TeamSwitcher } from "./team-switcher"*/ +import { + Sidebar, + SidebarContent, + SidebarFooter, + SidebarGroup, + SidebarGroupContent, + SidebarGroupLabel, + SidebarHeader, + SidebarMenu, + SidebarMenuAction, + SidebarMenuButton, + SidebarMenuItem, + SidebarMenuSub, + SidebarMenuSubButton, + SidebarMenuSubItem, + SidebarRail, +} from "@realms-world/ui/components/ui/sidebar"; import { Atom, Bird, BookOpen, Bot, + ChevronRight, Code2, Earth, Eclipse, @@ -14,30 +44,16 @@ import { Map, PieChart, Rabbit, - UserRoundPen, Settings2, SquareTerminal, Star, Turtle, + UserRoundPen, } from "lucide-react"; -import LordsIcon from "@/icons/lords.svg"; -/*import { NavProjects } from "./nav-projects" -import { NavSecondary } from "./nav-secondary" -import { NavUser } from "./nav-user" -import { StorageCard } from "./storage-card" -import { TeamSwitcher } from "./team-switcher"*/ -import { - Sidebar, - SidebarContent, - SidebarFooter, - SidebarHeader, - SidebarItem, - SidebarLabel, -} from "@realms-world/ui/components/ui/sidebar"; import { NavMain } from "./NavMain"; -import { NavUser } from "./NavUser"; import { NavSecondary } from "./NavSecondary"; +import { NavUser } from "./NavUser"; export enum Layer { "Ethereum", @@ -203,30 +219,73 @@ export const data = { export function AppSidebar() { return ( - - - Your Account - {/**/} + + + - - - - {/* + + + + {data.navMain.map((item) => ( + + + +
+ + + {item.title} + + + + {item.items.length ? ( + <> + + + + Toggle + + + + + {item.items.map((subItem) => ( + + + + {subItem.title} + + + + ))} + + + + ) : null} + + + ))} + + {/* Projects */} - {/* + {/* Help {/* */} + + + - - - + + ); } diff --git a/apps/nextjs/src/app/(app)/account/_components/sidebar/NavUser.tsx b/apps/nextjs/src/app/(app)/account/_components/sidebar/NavUser.tsx index c633f807..49b64a24 100644 --- a/apps/nextjs/src/app/(app)/account/_components/sidebar/NavUser.tsx +++ b/apps/nextjs/src/app/(app)/account/_components/sidebar/NavUser.tsx @@ -1,11 +1,8 @@ -import { - BadgeCheck, - Bell, - ChevronsUpDown, - CreditCard, - LogOut, -} from "lucide-react"; - +import ProfilePicture from "@/app/_components/ProfilePicture"; +import { StarknetLoginButton } from "@/app/_components/wallet/StarknetLoginButton"; +import EthereumLogo from "@/icons/ethereum.svg"; +import StarknetLogo from "@/icons/starknet.svg"; +import { shortenHex } from "@/utils/utils"; import { Avatar, AvatarFallback, @@ -20,9 +17,22 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@realms-world/ui/components/ui/dropdown-menu"; +import { + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + useSidebar, +} from "@realms-world/ui/components/ui/sidebar"; import { useAccount, useDisconnect } from "@starknet-react/core"; -import { shortenHex } from "@/utils/utils"; -import { StarknetLoginButton } from "@/app/_components/wallet/StarknetLoginButton"; +import { + BadgeCheck, + Bell, + ChevronsUpDown, + CreditCard, + LogOut, + Sparkles, +} from "lucide-react"; +import { useAccount as useL1Account } from "wagmi"; export function NavUser({ user, @@ -34,76 +44,101 @@ export function NavUser({ }; }) { const { address } = useAccount(); - const { disconnect } = useDisconnect(); + const { address: l1Address } = useL1Account(); + const { isMobile } = useSidebar(); + + const { disconnect } = useDisconnect(); return ( <> - - -
- - - CN - -
-
{user?.name}
-
-
- {address && shortenHex(address, 8)} -
-
-
- -
-
- - -
- - - CN - -
-
- {address && shortenHex(address, 8)} -
-
-
{user?.email}
-
-
-
-
- {/* - - - - Account - - - - Billing - - - - Notifications - - */} - - - - Log out - -
-
+ {address ? ( + + + + + + + + +
+ + {shortenHex(address, 8)} + +
+ +
+
+ + +
+ + + +
+ + {shortenHex(address, 8)} + + {user?.email} +
+
+
+ {l1Address && ( + +
+ + + +
+ + {shortenHex(l1Address, 8)} + + {user?.email} +
+
+
+ )} + + {/* + + + Upgrade to Pro + + + + + + + Account + + + + Billing + + + + Notifications + + + */} + disconnect()}> + + Log out + +
+
+
+
+ ) : ( + + )} ); } diff --git a/apps/nextjs/src/app/(app)/account/assets/Portfolio.tsx b/apps/nextjs/src/app/(app)/account/assets/Portfolio.tsx index 4bba872d..c344eb98 100644 --- a/apps/nextjs/src/app/(app)/account/assets/Portfolio.tsx +++ b/apps/nextjs/src/app/(app)/account/assets/Portfolio.tsx @@ -24,23 +24,20 @@ import { CollectionItemsDataFallback } from "@/app/_components/LoadingSkeletonGr export const Portfolio = ({ collectionAddress, selectable, + walletAddress, }: { collectionAddress?: string; selectable?: boolean; + walletAddress?: string; }) => { const [itemsFiltersOpen, setItemsFiltersOpen] = useState(false); const [viewType, setViewType] = useState("large-grid"); - - const [activeChain, setActiveChain] = useState("l1"); - const { address } = useAccount(); const { address: l2Address } = useL2Account(); - const { data: pendingWithdrawals } = usePendingRealmsWithdrawals({ - address, - status: "ACCEPTED_ON_L1", - }); const { marketplace: arkClient } = useArkClient(); + const address = walletAddress ?? l2Address; + const { data: infiniteData, fetchNextPage, @@ -48,10 +45,10 @@ export const Portfolio = ({ isFetching, isFetchingNextPage, } = useInfiniteQuery({ - queryKey: ["walletTokens", collectionAddress, l2Address], + queryKey: ["walletTokens", collectionAddress, address], refetchInterval: 10_000, placeholderData: keepPreviousData, - enabled: !!l2Address, + enabled: !!address, getNextPageParam: (lastPage: PortfolioCollectionApiResponse) => lastPage.next_page, // initialData: isSSR @@ -65,7 +62,7 @@ export const Portfolio = ({ getPortfolioTokens({ client: arkClient, page: pageParam, - walletAddress: l2Address ? l2Address : "", + walletAddress: address ? address : "", collectionAddress: collectionAddress, }), }); @@ -85,7 +82,6 @@ export const Portfolio = ({ const viewRef = useRef(null); const isInView = useInView(viewRef); useEffect(() => { - console.log(isInView); if (isInView && !isFetchingNextPage) fetchNextPage(); }, [isInView, fetchNextPage]); const { @@ -99,10 +95,10 @@ export const Portfolio = ({ } = useNftSelection({ userAddress: l2Address! }); return ( <> - {l2Address ? ( + {address ? (
setItemsFiltersOpen((previous) => !previous) diff --git a/apps/nextjs/src/app/(app)/account/assets/page.tsx b/apps/nextjs/src/app/(app)/account/assets/page.tsx index 7a88857c..35e30d31 100644 --- a/apps/nextjs/src/app/(app)/account/assets/page.tsx +++ b/apps/nextjs/src/app/(app)/account/assets/page.tsx @@ -1,8 +1,4 @@ import type { Metadata } from "next"; - -import { Collections } from "@realms-world/constants"; - -import { BridgeNftWrapper } from "./BridgeNftWrapper"; import { Portfolio } from "./Portfolio"; export function generateMetadata(): Metadata { diff --git a/apps/nextjs/src/app/(app)/account/delegates/page.tsx b/apps/nextjs/src/app/(app)/account/delegates/page.tsx index 04556c17..ce7a4c5f 100644 --- a/apps/nextjs/src/app/(app)/account/delegates/page.tsx +++ b/apps/nextjs/src/app/(app)/account/delegates/page.tsx @@ -14,11 +14,17 @@ export function generateMetadata(): Metadata { }; } -export default function Page({ - searchParams: { search }, -}: { - searchParams: { search?: string }; -}) { +export default async function Page( + props: { + searchParams: Promise<{ search?: string }>; + } +) { + const searchParams = await props.searchParams; + + const { + search + } = searchParams; + const filters: RouterInputs["delegates"]["all"] = { limit: 200, search: search, diff --git a/apps/nextjs/src/app/(app)/account/layout.tsx b/apps/nextjs/src/app/(app)/account/layout.tsx index 9b06c4ec..023f16b2 100644 --- a/apps/nextjs/src/app/(app)/account/layout.tsx +++ b/apps/nextjs/src/app/(app)/account/layout.tsx @@ -1,48 +1,46 @@ import dynamic from "next/dynamic"; +//import { ModeToggle } from '@realms-world/ui/components/ui/mode-toggle'; +import { cookies } from "next/headers"; import { StakingMigrationModal } from "@/app/_components/modal/StakingMigrationModal"; import { PageLayout } from "@/app/_components/PageLayout"; -import { SessionProvider } from "next-auth/react"; - import { - SidebarLayout, + SidebarProvider, SidebarTrigger, } from "@realms-world/ui/components/ui/sidebar"; -//import { ModeToggle } from '@realms-world/ui/components/ui/mode-toggle'; -import { cookies } from "next/headers"; +import { cn } from "@realms-world/utils"; +import { SessionProvider } from "next-auth/react"; + import { AuthWrapper } from "./_components/AuthWrapper"; import { AppSidebar } from "./_components/sidebar/AccountSidebar"; -import { cn } from "@realms-world/utils"; const SIDEBAR_STATE_COOKIE = "sidebar:state"; -export default function RootLayout({ +export default async function RootLayout({ children, }: { children: React.ReactNode; }) { const NftBridgeModal = dynamic( () => import("@/app/_components/modal/NftBridgeModal"), - { - ssr: false, - }, ); - const sidebarState = cookies().get(SIDEBAR_STATE_COOKIE)?.value ?? "true"; - const isSidebarOpen = sidebarState === "true"; + const sidebarState = + (await cookies()).get(SIDEBAR_STATE_COOKIE)?.value ?? "false"; + const isSidebarOpen = sidebarState !== "true"; return ( - +
{children}
-
+
diff --git a/apps/nextjs/src/app/(app)/account/lords/velords/VeLords.tsx b/apps/nextjs/src/app/(app)/account/lords/velords/VeLords.tsx index 89e07f09..5bfcdfc3 100644 --- a/apps/nextjs/src/app/(app)/account/lords/velords/VeLords.tsx +++ b/apps/nextjs/src/app/(app)/account/lords/velords/VeLords.tsx @@ -41,6 +41,7 @@ import { differenceInSeconds, getUnixTime, fromUnixTime } from "date-fns"; import { motion } from "framer-motion"; import { formatNumber } from "@realms-world/utils"; import Link from "next/link"; +import { useSimulateTransactions } from "@/hooks/useSimulateTransactions"; const WEEK_IN_SECONDS = 7 * 24 * 60 * 60; // 1 week in seconds const YEAR_IN_SECONDS = 365 * 24 * 60 * 60; // 1 year in seconds @@ -192,7 +193,7 @@ export const VeLords = () => { return 0n; }, [ownerLordsLock]); - const { claim, manageLock, withdraw } = useVeLords(); + const { claim, manageLock, withdraw, claimCall } = useVeLords(); const newLockEndTime = useMemo(() => { const currentTime = getUnixTime(new Date()); @@ -214,6 +215,12 @@ export const VeLords = () => { setLockWeeks(0); } }; + const { data: simulateData, error: simulateError } = useSimulateTransactions({ + calls: claimCall, + }); + + const lordsClaimable = + simulateData?.[0]?.transaction_trace.execute_invocation.result[2]; return (
@@ -521,8 +528,12 @@ export const VeLords = () => {
- You have 0 Lords - to claim + You have{" "} + + {lordsClaimable && + formatNumber(formatEther(BigInt(lordsClaimable)))} + {" "} + Lords to claim
diff --git a/apps/nextjs/src/app/(app)/blog/[slug]/page.tsx b/apps/nextjs/src/app/(app)/blog/[slug]/page.tsx index efba62af..46bf318d 100644 --- a/apps/nextjs/src/app/(app)/blog/[slug]/page.tsx +++ b/apps/nextjs/src/app/(app)/blog/[slug]/page.tsx @@ -19,16 +19,17 @@ async function getData({ id }: { id: string }) { }; } interface ArticlePageProps { - params: { + params: Promise<{ slug: string; - }; + }>; } -export async function generateMetadata({ - params, -}: { - params: { slug: string }; -}): Promise { +export async function generateMetadata( + props: { + params: Promise<{ slug: string }>; + } +): Promise { + const params = await props.params; const { article } = await getData({ id: params.slug }); return { @@ -56,7 +57,13 @@ export async function generateMetadata({ }; } -export default async function Article({ params: { slug } }: ArticlePageProps) { +export default async function Article(props: ArticlePageProps) { + const params = await props.params; + + const { + slug + } = params; + const { article } = await getData({ id: slug }); return ( diff --git a/apps/nextjs/src/app/(app)/blogs/BlogCard.tsx b/apps/nextjs/src/app/(app)/blogs/BlogCard.tsx index 83d523d2..8a55293b 100644 --- a/apps/nextjs/src/app/(app)/blogs/BlogCard.tsx +++ b/apps/nextjs/src/app/(app)/blogs/BlogCard.tsx @@ -3,34 +3,46 @@ import Link from "next/link"; import { Badge } from "@realms-world/ui/components/ui/badge"; import { Card } from "@realms-world/ui/components/ui/card"; import type { CollectionEntry } from "@/utils/keystatic"; +import { cn } from "@realms-world/utils"; export const BlogCard = ({ blog, slug, + horizontal, }: { blog: CollectionEntry<"blogs">; slug: string; + horizontal?: boolean; }) => { return ( - + {blog.title} -
- - {" "} - - +
+ {!horizontal && ( + + + + )} -

{blog.title}

-

{blog.subtitle}

+

{blog.title}

+ {!horizontal &&

{blog.subtitle}

}
diff --git a/apps/nextjs/src/app/(app)/blogs/BlogGrid.tsx b/apps/nextjs/src/app/(app)/blogs/BlogGrid.tsx index 8c0f9dad..8f6323c1 100644 --- a/apps/nextjs/src/app/(app)/blogs/BlogGrid.tsx +++ b/apps/nextjs/src/app/(app)/blogs/BlogGrid.tsx @@ -10,7 +10,7 @@ export const BlogGrid = async () => { }); return ( -
+
{blogsSortedByDate.map((blog, index) => ( ))} diff --git a/apps/nextjs/src/app/(app)/blogs/[slug]/_components/Sidebar.tsx b/apps/nextjs/src/app/(app)/blogs/[slug]/_components/Sidebar.tsx new file mode 100644 index 00000000..3e7df24e --- /dev/null +++ b/apps/nextjs/src/app/(app)/blogs/[slug]/_components/Sidebar.tsx @@ -0,0 +1,46 @@ +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import { + reader, + sortPostsByPublishDate, + CollectionEntry, +} from "@/utils/keystatic"; +import BlogCard from "../../BlogCard"; + +export const BlogSidebar = () => { + return ( +
+

Recent Posts

+ +
+ ); +}; + +export default async function RecentPosts({ + postNumber, +}: { + postNumber: number; +}) { + const allPosts = await reader().collections.blogs.all(); + const recentPosts = sortPostsByPublishDate(allPosts).slice(0, postNumber); + + return ( +
+
+
+ {recentPosts.map((post) => ( + <> + + + ))} +
+
+
+ ); +} diff --git a/apps/nextjs/src/app/(app)/blogs/[slug]/layout.tsx b/apps/nextjs/src/app/(app)/blogs/[slug]/layout.tsx index 5d744790..89ae1c4f 100644 --- a/apps/nextjs/src/app/(app)/blogs/[slug]/layout.tsx +++ b/apps/nextjs/src/app/(app)/blogs/[slug]/layout.tsx @@ -1,14 +1,21 @@ -"use client"; import { PageLayout } from "../../../_components/PageLayout"; import React from "react"; +import { BlogSidebar } from "./_components/Sidebar"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { - - return ( - {children} + +
+
+
{children}
+ +
+
+
); } diff --git a/apps/nextjs/src/app/(app)/blogs/[slug]/page.tsx b/apps/nextjs/src/app/(app)/blogs/[slug]/page.tsx index c69f7eff..14007237 100644 --- a/apps/nextjs/src/app/(app)/blogs/[slug]/page.tsx +++ b/apps/nextjs/src/app/(app)/blogs/[slug]/page.tsx @@ -13,11 +13,12 @@ import React from "react"; import Markdoc from "@markdoc/markdoc"; import { reader } from "@/utils/keystatic"; -export async function generateMetadata({ - params, -}: { - params: { slug: string }; -}): Promise { +export async function generateMetadata( + props: { + params: Promise<{ slug: string }>; + } +): Promise { + const params = await props.params; let blog = await reader().collections.blogs.read(params.slug); return { @@ -45,7 +46,8 @@ export async function generateMetadata({ }; } -export default async function Page({ params }: { params: { slug: string } }) { +export default async function Page(props: { params: Promise<{ slug: string }> }) { + const params = await props.params; const blog = await reader().collections.blogs.read(params.slug); if (!blog) { return
No Blog Found
; @@ -74,15 +76,14 @@ export default async function Page({ params }: { params: { slug: string } }) {

{blog?.title}

-

{blog?.subtitle}

-
- Posted on +
by {blog?.author}
+

{blog?.subtitle}

{blog?.title} -
+
{Markdoc.renderers.react(renderable, React)}
diff --git a/apps/nextjs/src/app/(app)/bridge/page.tsx b/apps/nextjs/src/app/(app)/bridge/page.tsx index 3983d94b..8bdae18c 100644 --- a/apps/nextjs/src/app/(app)/bridge/page.tsx +++ b/apps/nextjs/src/app/(app)/bridge/page.tsx @@ -10,11 +10,17 @@ export const metadata: Metadata = { description: "...", }; -export default function Page({ - searchParams: { action = "deposit" }, -}: { - searchParams: { action?: string }; -}) { +export default async function Page( + props: { + searchParams: Promise<{ action?: string }>; + } +) { + const searchParams = await props.searchParams; + + const { + action = "deposit" + } = searchParams; + const tabs = [ { name: "Deposit", diff --git a/apps/nextjs/src/app/(app)/collection/CollectionsList.tsx b/apps/nextjs/src/app/(app)/collection/CollectionsList.tsx index 6b4aea79..ec6e2534 100644 --- a/apps/nextjs/src/app/(app)/collection/CollectionsList.tsx +++ b/apps/nextjs/src/app/(app)/collection/CollectionsList.tsx @@ -1,11 +1,11 @@ -import { CollectionCard } from "@/app/_components/CollectionCard"; +/*import { CollectionCard } from "@/app/_components/CollectionCard"; import { SUPPORTED_L1_CHAIN_ID } from "@/constants/env"; import { CollectionAddresses } from "@realms-world/constants"; -import { getCollections } from "@/lib/reservoir/getCollections"; -import { REALMS_L2_COLLECTIONS } from "@realms-world/constants/src/Collections"; +import { getCollections } from "@/lib/reservoir/getCollections";*/ import { ArkCollectionCardFetcher } from "@/app/_components/ArkCollectionCardFetcher"; +import { REALMS_L2_COLLECTIONS } from "@realms-world/constants/src/Collections"; export const metadata = { title: "Lootverse Collections", @@ -13,18 +13,18 @@ export const metadata = { "Various collections of the Lootverse - Created for adventurers by Bibliotheca DAO", }; -export default async function CollectionsList() { - const { collections } = await getCollections([ +export default function CollectionsList() { + /*const { collections } = await getCollections([ { contract: CollectionAddresses.realms[ SUPPORTED_L1_CHAIN_ID ] as `0x${string}`, }, - ]); + ]);*/ return (
- {collections?.map((collection, index) => { + {/*collections?.map((collection, index) => { return ( ); - })} + })*/} {REALMS_L2_COLLECTIONS.map((collection, index) => ( ))} diff --git a/apps/nextjs/src/app/(app)/collection/ViewOnMarketplace.tsx b/apps/nextjs/src/app/(app)/collection/ViewOnMarketplace.tsx index a2a48ef5..e79b23a8 100644 --- a/apps/nextjs/src/app/(app)/collection/ViewOnMarketplace.tsx +++ b/apps/nextjs/src/app/(app)/collection/ViewOnMarketplace.tsx @@ -1,18 +1,33 @@ +import Link from "next/link"; import { Button } from "@realms-world/ui/components/ui/button"; -import Link from "next/link" +import { ShoppingCart } from "lucide-react"; -export const ViewOnMarketplace = ({ collection, tokenId }: { collection: string, tokenId?: number }) => { - // Define the base URL - const baseURL = 'https://market.realms.world/'; +export const ViewOnMarketplace = ({ + collection, + tokenId, + icon, +}: { + collection: string; + tokenId?: number | string; + icon?: boolean; +}) => { + // Define the base URL + const baseURL = "https://market.realms.world/"; - // Construct the URL based on whether `tokenId` is provided - const url = tokenId - ? `${baseURL}token/${collection}/${tokenId}` - : `${baseURL}collection/${collection}`; + // Construct the URL based on whether `tokenId` is provided + const url = tokenId + ? `${baseURL}token/${collection}/${tokenId}` + : `${baseURL}collection/${collection}`; - return ( - - - - ) -} \ No newline at end of file + return ( + + {icon ? ( + + ) : ( + + )} + + ); +}; diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFilters.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFilters.tsx new file mode 100644 index 00000000..1c01da59 --- /dev/null +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFilters.tsx @@ -0,0 +1,132 @@ +"use client"; + +import type { Filters } from "@/types/ark"; +import { useState } from "react"; +import { getCollectionTraits } from "@/lib/ark/getCollectionTraits"; +import { useArkClient } from "@/lib/ark/useArkClient"; +import { Button } from "@realms-world/ui/components/ui/button"; +import { + Dialog, + DialogContent, + DialogTitle, +} from "@realms-world/ui/components/ui/dialog"; +import { ScrollArea } from "@realms-world/ui/components/ui/scroll-area"; +import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; + +import CollectionFiltersContent from "./CollectionFiltersContent"; +import CollectionFiltersTrait from "./CollectionFiltersTrait"; + +interface CollectionFiltersProps { + collectionAddress: string; + filters: Filters; + onFiltersChange: (newFilters: Filters) => Promise; + isOpen: boolean; + buyNow: boolean; + setBuyNow: (buyNow: boolean) => void; +} + +export default function CollectionFilters({ + collectionAddress, + filters, + onFiltersChange, + isOpen, + buyNow, + setBuyNow, +}: CollectionFiltersProps) { + const { marketplace: arkClient } = useArkClient(); + + const { data } = useSuspenseQuery({ + queryKey: ["collectionTraits", collectionAddress], + queryFn: async () => { + return await getCollectionTraits({ + client: arkClient, + collectionAddress, + }); + }, + }); + const [searchQuery, setSearchQuery] = useState(""); + + const handleTraitChange = async (name: string, value: string) => { + const values = filters.traits[name] ?? []; + + const newValues = values.includes(value) + ? values.filter((v) => v !== value) + : [...values, value]; + + const traits = Object.fromEntries( + Object.entries({ + ...filters.traits, + [name]: newValues, + }).filter(([_, v]) => v.length > 0), + ); + + await onFiltersChange({ + ...filters, + traits, + }); + }; + + if (!isOpen) { + return null; + } + + const filteredData = + data && + Object.fromEntries( + Object.entries(data).map(([key, value]) => { + const filtered = Object.fromEntries( + Object.entries(value).filter(([k]) => + k.toLowerCase().includes(searchQuery.toLowerCase()), + ), + ); + + return [key, filtered]; + }), + ); + + const hasTraits = + filteredData && + Object.values(filteredData).some((trait) => Object.keys(trait).length > 0); + + const showTraitsSection = data && Object.keys(data).length > 0; + + return ( + + + {showTraitsSection && ( +
+
+ Traits +
+ {/*
+ setSearchQuery(e.target.value)} + /> +
*/} +
+ {/*searchQuery.length > 0 && !hasTraits && ( +
+
+ No traits found for "{searchQuery}" +
+
+ )*/} + {Object.keys(filteredData).map((key: string) => ( + + ))} +
+
+ )} +
+ ); +} diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFiltersContent.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFiltersContent.tsx new file mode 100644 index 00000000..8bc0eb24 --- /dev/null +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFiltersContent.tsx @@ -0,0 +1,43 @@ +import { Label } from "@realms-world/ui/components/ui/label"; +import { + RadioGroup, + RadioGroupItem, +} from "@realms-world/ui/components/ui/radio-group"; + +interface CollectionFiltersContentProps { + buyNow: boolean; + setBuyNow: (buyNow: boolean) => void; +} + +export default function CollectionFiltersContent({ + buyNow, + setBuyNow, +}: CollectionFiltersContentProps) { + function onValueChange(value: string) { + if (value === "buy-now") { + setBuyNow(true); + return; + } + setBuyNow(false); + } + return ( +
+

Status

+ + +
+ + +
+
+ + +
+
+
+ ); +} diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFiltersTrait.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFiltersTrait.tsx new file mode 100644 index 00000000..6816b46e --- /dev/null +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/CollectionFiltersTrait.tsx @@ -0,0 +1,86 @@ +"use client"; +import { useState } from "react"; +import { ChevronDown } from "lucide-react"; + +import { cn } from "@realms-world/utils"; +import { Checkbox } from "@realms-world/ui/components/ui/checkbox"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@realms-world/ui/components/ui/collapsible"; + +import type { CollectionTrait } from "@/types/ark"; + +interface CollectionFiltersTraitProps { + name: string; + trait: CollectionTrait; + selectedTraits?: Record; + onChange: (traitName: string, value: string) => void; +} + +function CollectionFiltersTrait({ + name, + trait, + selectedTraits = {}, + onChange, +}: CollectionFiltersTraitProps) { + const [isOpen, setIsOpen] = useState(false); + const isActive = selectedTraits[name]?.length; + const count = Object.values(trait).length; + + if (!count) { + return null; + } + + return ( + + +
+
{name}
+
+
+ {count} +
+ +
+
+
+ +
+ {Object.keys(trait).map((key) => ( + + ))} +
+
+
+ ); +} + +export default CollectionFiltersTrait; diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2CollectionSummary.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2CollectionSummary.tsx index a92507a1..0587b044 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2CollectionSummary.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2CollectionSummary.tsx @@ -3,24 +3,38 @@ import Image from "next/image"; import Link from "next/link"; import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; import LordsIcon from "@/icons/lords.svg"; -import { getGamesByContract } from "@/utils/getters"; import type { Collections, Game } from "@realms-world/constants"; import { CollectionDetails, - games, getCollectionAddresses, } from "@realms-world/constants"; import { Button } from "@realms-world/ui/components/ui/button"; import { ViewOnMarketplace } from "../../ViewOnMarketplace"; import { getCollections } from "@/lib/ark/getCollection"; import { marketPlaceClientBuilder } from "@/lib/ark/client"; +import { reader } from "@/utils/keystatic"; +import { formatEther } from "viem"; +import Gamepad from "@/icons/gamepad.svg"; export default async function L2CollectionSummary({ collectionId, }: { collectionId: string; }) { + const collectionContent = + await reader().collections.collections.read(collectionId); + + const collectionGames = await Promise.all( + collectionContent.games.map(async (game, index) => { + return ( + { + ...(await reader().collections.games.read(game ?? "")), + slug: collectionContent.games[index], + } ?? "" + ); + }), + ); const l2CollectionAddress = getCollectionAddresses(collectionId)?.[SUPPORTED_L2_CHAIN_ID]; @@ -29,8 +43,10 @@ export default async function L2CollectionSummary({ } // in server components, we can directly get client with server builder const client = marketPlaceClientBuilder(fetch); - const erc721Collection = await getCollections({ client, collectionAddress: l2CollectionAddress }); - + const erc721Collection = await getCollections({ + client, + collectionAddress: l2CollectionAddress, + }); const contract_details: ContractDetails[] = [ { title: "Type", @@ -43,31 +59,32 @@ export default async function L2CollectionSummary({ ]; const statistics = [ - /* { - value: collection.floorSale?.["1day"], + /*{ + value: erc721Collection.data.top_offer, title: "Top Offer", - }, + },*/ { value: - collection.floorAsk?.price?.amount?.raw && - formatEther(BigInt(collection?.floorAsk?.price?.amount?.raw)), + erc721Collection.data.floor && + formatEther(BigInt(erc721Collection.data.floor)), title: "Floor", - },*/ + icon: , + }, //{ value: collection.onSaleCount, title: "Listed" }, { value: erc721Collection.data.total_volume, title: "Total Volume", icon: , }, - //{ value: collection.tokenCount, title: "Count" }, + { + value: erc721Collection.data.token_count, + title: "Items", + }, + { value: erc721Collection.data.owner_count, title: "Owner Count" }, ]; - const marketplaceId = erc721Collection[0]?.marketplaceId?.toString(); - const compatibleGames = marketplaceId - ? getGamesByContract(games, marketplaceId) - : []; return ( -
+
-
-

{CollectionDetails[collectionId as Collections].displayName}

- - - {compatibleGames.length > 0 && ( - - )} +
+
+

+ {CollectionDetails[collectionId as Collections].displayName} +

+ -
- {statistics.map((statistic, index) => { - return ( - - ); - })} + {collectionGames.length > 0 && ( + + )} +
+
+
+ {statistics.map((statistic, index) => { + return ( + + ); + })} +
+
- -
); @@ -124,20 +145,19 @@ export const StatisticsBox = ({ icon?: React.ReactNode; }) => { return ( -
+
- {" "} +
{title}
+ {icon && {icon}} {value ? Number(value).toLocaleString("en-US", { - style: "decimal", - maximumFractionDigits: 2, - }) - : null}{" "} - {icon && icon} + style: "decimal", + maximumFractionDigits: 2, + }) + : null}
-
{title}
); }; @@ -152,7 +172,7 @@ export const ContractDetailsList = ({ {contract_details.map((detail, index) => { return (
- {detail.title} {detail.value} + {detail.title} {detail.value}
); })} @@ -162,11 +182,12 @@ export const ContractDetailsList = ({ export const CompatibleGames = ({ games }: { games: Game[] }) => { return ( -
+
+ : {games.map((game, index) => { return ( - ); })} diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Card.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Card.tsx index 89a9b892..5d643ada 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Card.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Card.tsx @@ -1,21 +1,26 @@ -import Image from "next/image"; +import type { CollectionToken, PortfolioToken } from "@/types/ark"; import Link from "next/link"; import { AnimatedMap } from "@/app/_components/AnimatedMap"; +import Media from "@/app/_components/Media"; +import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; import { useLordsPrice } from "@/hooks/lords/useLordsPrice"; -import type { CollectionToken, PortfolioToken } from "@/types/ark"; - +import { useTokenListing } from "@/hooks/market/useTokenListing"; +import { useTokenMetadata } from "@/hooks/market/useTokenMetadata"; import { useStarkDisplayName } from "@/hooks/useStarkName"; import LordsIcon from "@/icons/lords.svg"; - -import type { RouterOutputs } from "@realms-world/api"; +import { + CollectionAddresses, + getCollectionFromAddress, +} from "@realms-world/constants"; import { Button } from "@realms-world/ui/components/ui/button"; -import { cn } from "@realms-world/utils"; +import { cn, formatNumber } from "@realms-world/utils"; +import { Info } from "lucide-react"; +import { formatEther } from "viem"; -import { CardAction } from "./CardAction"; -import { useTokenListing } from "@/hooks/market/useTokenListing"; -import { useTokenMetadata } from "@/hooks/market/useTokenMetadata"; import { ViewOnMarketplace } from "../../ViewOnMarketplace"; -import Media from "@/app/_components/Media"; +import { CardAction } from "./CardAction"; +import RealmResources from "./RealmResources"; + export const L2ERC721Card = ({ token, layout = "grid", @@ -45,7 +50,7 @@ export const L2ERC721Card = ({ {token.metadata?.image ? ( { !selectable && ( - +
+ + + + +
) /* */ } @@ -118,15 +133,13 @@ const TokenAttributes = ({ token, attributeKeys, }: { - token: - | CollectionToken - | RouterOutputs["erc721Tokens"]["all"]["items"][number]; + token: CollectionToken; attributeKeys: string[]; }) => { const metadata = useTokenMetadata(token); if (!metadata?.attributes) return null; - +
{attributeKeys.map((key: string) => { const attribute = metadata.attributes.find( @@ -146,49 +159,48 @@ const TokenAttributes = ({ const GridDetails = ({ token, }: { - token: CollectionToken; + token: CollectionToken | PortfolioToken; address?: string; }) => (
{token.metadata?.name ?? ""} +
+ + {/*token.last_price && ( + + {token.last_price} + + + )*/} +
- -
- {/* - {token.lastPrice && ( - - {token.lastPrice} - - - )}*/} +
+ {token.metadata?.attributes && + token.collection_address == + CollectionAddresses.realms[SUPPORTED_L2_CHAIN_ID] && ( + + )}
); -const Price = ({ - token, -}: { - token: RouterOutputs["erc721Tokens"]["all"]["items"][number] & { - listings: RouterOutputs["erc721MarketEvents"]["all"]["items"]; - }; -}) => { +const Price = ({ token }: { token: CollectionToken | PortfolioToken }) => { const { lordsPrice } = useLordsPrice(); - const listing = useTokenListing(token); - if (undefined === listing || null === listing) return null; return (
- {token.price && listing.price && ( + {token.price && (
- {listing.price} + {formatEther(BigInt(token.price))}
- {((lordsPrice?.usdPrice ?? 0) * parseFloat(listing.price)).toFixed( - 2, - )}{" "} + {( + (lordsPrice?.usdPrice ?? 0) * + parseFloat(formatEther(BigInt(token.price))) + ).toFixed(2)}{" "} USD
diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Table.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Table.tsx index 54a91190..445a490f 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Table.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/L2ERC721Table.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useRef } from "react"; +import { Suspense, useEffect, useRef, useState } from "react"; import Link from "next/link"; import { useSearchParams } from "next/navigation"; import { NftActions } from "@/app/(app)/account/assets/NftActions"; @@ -18,6 +18,9 @@ import { TokenCardSkeleton } from "../../TokenCardSkeleton"; import { L2ERC721Card } from "./L2ERC721Card"; import { useArkClient } from "@/lib/ark/useArkClient"; import { useSuspenseInfiniteQuery } from "@tanstack/react-query"; +import { parseAsBoolean, parseAsJson, useQueryState } from "nuqs"; +import { Filters } from "@/types/ark"; +import CollectionFilters from "./CollectionFilters"; const L2ERC721Table = ({ contractAddress, @@ -36,32 +39,63 @@ const L2ERC721Table = ({ }) => { const { isGrid } = useUIStore((state) => state); const grid = - "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5"; + "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 p-3"; const list = "grid grid-cols-1 w-full"; const ref = useRef(null); const searchParams = useSearchParams(); + const [filtersPanelOpen, setFiltersPanelOpen] = useState(true); + const [filtersDialogOpen, setFiltersDialogOpen] = useState(false); + const sortDirection = searchParams.get("sortDirection"); const sortBy = searchParams.get("sortBy"); - const buyNowOnly = searchParams.get("Status"); + const [buyNow, setBuyNow] = useQueryState( + "buy_now", + parseAsBoolean.withDefault(false), + ); + const [filters, setFilters] = useQueryState( + "filters", + parseAsJson().withDefault({ + traits: {}, + }), + ); - const attributesObject: Record = {}; - for (const [key, value] of searchParams.entries()) { - attributesObject[key] = value; - } - const attributeFilter = cleanQuery(attributesObject); - - const filters: RouterInputs["erc721Tokens"]["all"] = { - limit, - contractAddress, - attributeFilter: attributeFilter, - sortDirection: sortDirection, - orderBy: sortBy, - buyNowOnly: buyNowOnly == "Buy Now Only", + const toggleFiltersPanel = () => setFiltersPanelOpen((open) => !open); + + const handlerFiltersChange = async (newFilters: Filters) => { + await setFilters(newFilters); }; + const resetFiltersTraits = async () => { + await setFilters({ + ...filters, + traits: {}, + }); + }; + + const removeFiltersTraits = async (key: string, value: string) => { + const newTraits = { ...filters.traits }; + const values = newTraits[key] ?? []; + const newValues = values.filter((v) => v !== value); + + if (newValues.length === 0) { + delete newTraits[key]; + } else { + newTraits[key] = newValues; + } + + await setFilters({ + ...filters, + traits: newTraits, + }); + }; + + const filtersCount = Object.values(filters.traits).reduce( + (acc, traitValues) => acc + traitValues.length, + 0, + ); if (ownerAddress) { filters.owner = ownerAddress; } @@ -73,15 +107,17 @@ const L2ERC721Table = ({ hasNextPage, isFetching, } = useSuspenseInfiniteQuery({ - queryKey: ["erc721Tokens", contractAddress, ownerAddress, filters], + queryKey: ["erc721Tokens", contractAddress, ownerAddress, filters, buyNow], queryFn: async ({ pageParam }) => { return await getCollectionTokens({ client: arkClient, collectionAddress: contractAddress, page: pageParam ?? 1, - ...filters, + buyNowOnly: buyNow, + filters, }); }, + initialPageParam: undefined as number | undefined, getNextPageParam: (lastPage) => lastPage.next_page, }); @@ -105,7 +141,17 @@ const L2ERC721Table = ({ } return ( - <> +
+ + + {selectable && ( {infiniteScroll &&
} - +
); }; export default L2ERC721Table; diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/ListingCard.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/ListingCard.tsx index 67f41120..ded4739d 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/ListingCard.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/ListingCard.tsx @@ -23,11 +23,14 @@ export const ListingCard = ({ listing, token }: ActivityCardProps) => { const getLocalizedDate = useMemo(() => { return expiryDiff.toLocaleString(); }, [expiryDiff]); - const price = useTokenPrice(listing.listing.start_amount, listing.listing.currency_address); + const price = useTokenPrice( + listing.listing.start_amount, + listing.listing.currency_address, + ); return ( -
-
+
+
{price} @@ -55,7 +58,7 @@ export const ListingCard = ({ listing, token }: ActivityCardProps) => {
- {token && ( + {/*token && ( @@ -67,7 +70,7 @@ export const ListingCard = ({ listing, token }: ActivityCardProps) => { //collectionId={activity.collection_id} orderId={0} /> - )} + )*/}
); diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/RealmResources.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/RealmResources.tsx new file mode 100644 index 00000000..0100c441 --- /dev/null +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/RealmResources.tsx @@ -0,0 +1,72 @@ +import { ResourceIcon } from "@realms-world/ui/components/ui/resource-icon"; +import { TokenMetadataAttribute } from "@/types/ark"; +import { useState } from "react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@realms-world/ui/components/ui/tooltip"; // Assuming you're using a tooltip library +import { Button } from "@realms-world/ui/components/ui/button"; + +export default function RealmResources({ + traits, +}: { + traits: TokenMetadataAttribute[]; +}) { + const resources = traits.filter((trait) => trait.trait_type === "Resource"); + const [showMore, setShowMore] = useState(false); + const hiddenCount = resources.length - 4; + + return ( +
+ {resources.slice(0, 4).map((resource, index) => ( +
+ +
+ ))} + {resources.length > 4 && ( + <> + + + + + + + +
+ {resources.slice(4).map((resource, index) => ( +
+
+ {resource.value} + +
+
+ ))} +
+
+
+
+ + )} +
+ ); +} diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/activity/page.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/activity/page.tsx index 95eb0155..179db52a 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/activity/page.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/activity/page.tsx @@ -8,13 +8,14 @@ import { ActivityCard } from "./ActivityCard"; import { CollectionActivity } from "./CollectionActivity"; import { L2ActivityTable } from "./L2ActivityTable"; -export default async function Page({ - params, - searchParams, -}: { - params: { id: string }; - searchParams: { types?: string[] | string }; -}) { +export default async function Page( + props: { + params: Promise<{ id: string }>; + searchParams: Promise<{ types?: string[] | string }>; + } +) { + const searchParams = await props.searchParams; + const params = await props.params; const tokenAddresses = getCollectionAddresses(params.id); if (!tokenAddresses) { return
Collection Not Found
; diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/analytics/page.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/analytics/page.tsx index 1114667c..a4887ed5 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/analytics/page.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/analytics/page.tsx @@ -8,7 +8,8 @@ import { getCollectionAddresses } from "@realms-world/constants"; import { OwnerDistribution } from "./OwnerDistribution"; import { TopOwners } from "./TopOwners"; -export default async function Page({ params }: { params: { id: string } }) { +export default async function Page(props: { params: Promise<{ id: string }> }) { + const params = await props.params; const tokenAddresses = getCollectionAddresses(params.id); if (!tokenAddresses?.[SUPPORTED_L1_CHAIN_ID]) { return

Coming Soon

; diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/layout.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/layout.tsx index d5581f30..3750a05d 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/layout.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/layout.tsx @@ -5,19 +5,24 @@ import { env } from "env"; import { Collections } from "@realms-world/constants"; import { NavLink } from "@realms-world/ui/components/ui/nav-link"; -export default function RootLayout({ - children, - params, -}: { - children: React.ReactNode; - params: { id: string }; -}) { +export default async function RootLayout( + props: { + children: React.ReactNode; + params: Promise<{ id: string }>; + } +) { + const params = await props.params; + + const { + children + } = props; + const isMintable = env.NEXT_PUBLIC_IS_TESTNET == "true" && params.id == (Collections.GOLDEN_TOKEN as string); const tabs = [ { - name: "Trade", + name: "Items", link: "", }, ]; @@ -36,24 +41,21 @@ export default function RootLayout({ );*/ return ( -
-
- -
- {tabs.map((tab) => ( - - {tab.name} - - ))} -
-
{children}
+
+ +
+ {tabs.map((tab) => ( + + {tab.name} + + ))}
+ {children}
); } diff --git a/apps/nextjs/src/app/(app)/collection/[id]/(list)/page.tsx b/apps/nextjs/src/app/(app)/collection/[id]/(list)/page.tsx index c9eddd26..d80e1e57 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/(list)/page.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/(list)/page.tsx @@ -1,6 +1,6 @@ import type { Metadata } from "next"; import { Suspense } from "react"; -import { SUPPORTED_L1_CHAIN_ID, SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; +import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; import { getAttributes } from "@/lib/reservoir/getAttributes"; import { getToken } from "@/lib/reservoir/getToken"; import { api } from "@/trpc/server"; @@ -17,11 +17,12 @@ import { TradeLayout } from "./Trade"; //export const runtime = "edge"; -export function generateMetadata({ - params, -}: { - params: { id: string }; -}): Metadata { +export async function generateMetadata( + props: { + params: Promise<{ id: string }>; + } +): Promise { + const params = await props.params; const collection = CollectionDetails[params.id as Collections]; return { title: `${collection.displayName}`, @@ -35,18 +36,20 @@ export function generateMetadata({ }; } -export default function Page({ - params, - searchParams, -}: { - params: { id: string }; - searchParams?: { - page?: string; - }; -}) { +export default async function Page( + props: { + params: Promise<{ id: string }>; + searchParams?: Promise<{ + page?: string; + }>; + } +) { + const searchParams = await props.searchParams; + const params = await props.params; const tokenAddresses = getCollectionAddresses(params.id); - if (!tokenAddresses) { + const l2TokenAddress = tokenAddresses?.[SUPPORTED_L2_CHAIN_ID]; + if (!l2TokenAddress) { return
Collection Not Found
; } /* isSepoliaGoldenToken = @@ -56,7 +59,7 @@ export default function Page({ if (isSepoliaGoldenToken) { return ; }*/ - if (tokenAddresses[SUPPORTED_L2_CHAIN_ID]) { + /* if (tokenAddresses[SUPPORTED_L2_CHAIN_ID]) { const l2TokenAddress = tokenAddresses[SUPPORTED_L2_CHAIN_ID]; if (typeof l2TokenAddress === "string") { return ; @@ -72,7 +75,9 @@ export default function Page({ /> ); } - } + }*/ + + return ; } const L2TokenData = ({ tokenAddress }: { tokenAddress: string }) => { diff --git a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/L2Token.tsx b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/L2Token.tsx index d34a480c..cd1ce5ae 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/L2Token.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/L2Token.tsx @@ -105,7 +105,7 @@ export const L2Token = ({ ) : ( "Not listed" )}{" "} - {erc721Token.owner == padAddress(address) ? ( + {/*erc721Token.owner == padAddress(address) ? ( ) : (
@@ -122,7 +122,7 @@ export const L2Token = ({ /> )}
- )} + )*/}
{ const { address } = useAccount(); - const comptatible_games = collection.id + /*const comptatible_games = collection.id ? getGamesByContract(games, collection.id) - : undefined; + : undefined;*/ const owner = address ? token?.owner?.toUpperCase() === address.toUpperCase() @@ -47,9 +52,9 @@ export const TokenContent = ({ token, collection }: Props) => { name: "Games", content: (
- {comptatible_games?.map((game, index) => { + {/*comptatible_games?.map((game, index) => { return ; - })} + })*/}
), }, diff --git a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/TokenInformation.tsx b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/TokenInformation.tsx index c3253d7a..b4f1ebb9 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/TokenInformation.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/TokenInformation.tsx @@ -40,7 +40,7 @@ export const TokenInformation = ({ }) => { return ( <> -
+
{image ? ( -
-
- +
+
+ + { + CollectionDetails[collectionId as keyof typeof CollectionDetails] + .displayName + } +
#{tokenId}
-

{decodeURIComponent(name ?? "")}

+

+ {decodeURIComponent(name ?? "")} +

{owner && (
Owner
diff --git a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/layout.tsx b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/layout.tsx index 5be6e312..aa60c754 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/layout.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/layout.tsx @@ -5,9 +5,5 @@ export default function RootLayout({ }: { children: React.ReactNode; }) { - return ( -
- {children} -
- ); + return
{children}
; } diff --git a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/page.tsx b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/page.tsx index e35440b0..ba90ddef 100644 --- a/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/page.tsx +++ b/apps/nextjs/src/app/(app)/collection/[id]/[tokenId]/page.tsx @@ -17,11 +17,18 @@ import { TokenInformation } from "./TokenInformation"; import { marketPlaceClientBuilder } from "@/lib/ark/client"; import { getToken } from "@/lib/ark/getToken"; -export function generateMetadata({ - params: { tokenId, id }, -}: { - params: { id: string; tokenId: string }; -}): Metadata { +export async function generateMetadata( + props: { + params: Promise<{ id: string; tokenId: string }>; + } +): Promise { + const params = await props.params; + + const { + tokenId, + id + } = params; + const collection = CollectionDetails[id as Collections].displayName; return { title: `${collection} #${tokenId}`, @@ -35,11 +42,12 @@ export function generateMetadata({ }; } -export default function Page({ - params, -}: { - params: { id: string; tokenId: string }; -}) { +export default async function Page( + props: { + params: Promise<{ id: string; tokenId: string }>; + } +) { + const params = await props.params; const tokenAddresses = getCollectionAddresses(params.id); if (!tokenAddresses) { return
Collection Not Found
; diff --git a/apps/nextjs/src/app/(app)/events/[slug]/page.tsx b/apps/nextjs/src/app/(app)/events/[slug]/page.tsx index 3a7e76c2..1d108a1f 100644 --- a/apps/nextjs/src/app/(app)/events/[slug]/page.tsx +++ b/apps/nextjs/src/app/(app)/events/[slug]/page.tsx @@ -7,11 +7,12 @@ import Markdoc from "@markdoc/markdoc"; import { Button } from "@realms-world/ui/components/ui/button"; import { reader } from "@/utils/keystatic"; -export async function generateMetadata({ - params, -}: { - params: { slug: string }; -}): Promise { +export async function generateMetadata( + props: { + params: Promise<{ slug: string }>; + } +): Promise { + const params = await props.params; let event = await reader().collections.events.read(params.slug); return { title: `${event?.name}`, @@ -19,7 +20,8 @@ export async function generateMetadata({ }; } -export default async function Page({ params }: { params: { slug: string } }) { +export default async function Page(props: { params: Promise<{ slug: string }> }) { + const params = await props.params; const event = await reader().collections.events.read(params.slug); if (!event) { return
No Event Found
; diff --git a/apps/nextjs/src/app/(app)/games/[slug]/layout.tsx b/apps/nextjs/src/app/(app)/games/[slug]/layout.tsx index 16551c4e..53d6f4f7 100644 --- a/apps/nextjs/src/app/(app)/games/[slug]/layout.tsx +++ b/apps/nextjs/src/app/(app)/games/[slug]/layout.tsx @@ -1,14 +1,15 @@ "use client"; -import React from "react"; +import React, { use } from "react"; -export default function RootLayout({ - children, - params, -}: { +export default function RootLayout(props: { children: React.ReactNode; - params: { id: string }; + params: Promise<{ id: string }>; }) { + const params = use(props.params); + + const { children } = props; + const defaultImage = "/backgrounds/dummy_background.png"; // const imageUrl = // "url(" + @@ -16,15 +17,14 @@ export default function RootLayout({ // ")"; return (
{children} -
); } diff --git a/apps/nextjs/src/app/(app)/games/[slug]/page.tsx b/apps/nextjs/src/app/(app)/games/[slug]/page.tsx index 997d7501..59d14418 100644 --- a/apps/nextjs/src/app/(app)/games/[slug]/page.tsx +++ b/apps/nextjs/src/app/(app)/games/[slug]/page.tsx @@ -1,48 +1,49 @@ import type { Metadata } from "next"; +import React from "react"; import Image from "next/image"; import Link from "next/link"; import { StatusDot } from "@/app/_components/StatusDot"; import { reader } from "@/utils/keystatic"; import Markdoc from "@markdoc/markdoc"; -import React from "react"; import { CHAIN_IDS_TO_NAMES } from "@realms-world/constants"; - -import { Button } from "@realms-world/ui/components/ui/button"; import { Badge } from "@realms-world/ui/components/ui/badge"; import { Breadcrumb, - BreadcrumbList, BreadcrumbItem, BreadcrumbLink, + BreadcrumbList, BreadcrumbSeparator, } from "@realms-world/ui/components/ui/breadcrumb"; +import { Button } from "@realms-world/ui/components/ui/button"; import { Carousel, CarouselContent, CarouselItem, - CarouselPrevious, CarouselNext, + CarouselPrevious, } from "@realms-world/ui/components/ui/carousel"; import { Tabs, + TabsContent, TabsList, TabsTrigger, - TabsContent, } from "@realms-world/ui/components/ui/tabs"; -export async function generateMetadata({ - params, -}: { - params: { slug: string }; +export async function generateMetadata(props: { + params: Promise<{ slug: string }>; }): Promise { - let game = await reader().collections.games.read(params.slug); + const params = await props.params; + const game = await reader().collections.games.read(params.slug); return { title: `${game?.title}`, description: `${params.slug} - Created for Adventurers by Bibliotheca DAO`, }; } -export default async function Page({ params }: { params: { slug: string } }) { +export default async function Page(props: { + params: Promise<{ slug: string }>; +}) { + const params = await props.params; const keyStaticGame = await reader().collections.games.read(params.slug); if (!keyStaticGame) return; @@ -53,15 +54,15 @@ export default async function Page({ params }: { params: { slug: string } }) { throw new Error("Invalid content"); } const renderable = Markdoc.transform(node); - const screenshotList = keyStaticGame?.screenshots; + const screenshotList = keyStaticGame.screenshots; const list = [...screenshotList].map((image, index) => ({ src: `/content/games/${params.slug}/${image}`, - alt: `${keyStaticGame?.title} Screenshot ${index}`, + alt: `${keyStaticGame.title} Screenshot ${index}`, })); // grab studio via developer slug from game so we can spit out the studio's title instead of its slug const studio = await reader().collections.studios.read( - keyStaticGame?.developer || "", + keyStaticGame.developer || "", ); const tabs = [ @@ -80,7 +81,7 @@ export default async function Page({ params }: { params: { slug: string } }) {
- {keyStaticGame?.tokens?.map((token, index) => ( + {keyStaticGame.tokens.map((token, index) => ( //token === Tokens.LORDS ? ( @@ -92,7 +93,7 @@ export default async function Page({ params }: { params: { slug: string } }) { ),*/ ))} - {keyStaticGame?.collections?.map((collection, index) => ( + {keyStaticGame.collections.map((collection, index) => ( @@ -108,17 +109,17 @@ export default async function Page({ params }: { params: { slug: string } }) { { key: "Studio", value: ( - + {studio?.title} ), }, - { key: "Status", value: keyStaticGame?.status }, + { key: "Status", value: keyStaticGame.status }, { key: "Chain", value: (
- {keyStaticGame?.chains.map((a, i) => + {keyStaticGame.chains.map((a, i) => String(a) === "420" ? ( {" "} @@ -143,7 +144,7 @@ export default async function Page({ params }: { params: { slug: string } }) { key: "Category", value: (
- {keyStaticGame?.genres?.map((a, i) => ( + {keyStaticGame.genres.map((a, i) => ( {a} @@ -151,14 +152,14 @@ export default async function Page({ params }: { params: { slug: string } }) {
), }, - { key: "Token", value: keyStaticGame?.tokens }, + { key: "Token", value: keyStaticGame.tokens }, { key: "White Paper", value: ( <> - {keyStaticGame?.whitepaper ? ( + {keyStaticGame.whitepaper ? ( ) : ( "No whitepaper available" @@ -170,9 +171,9 @@ export default async function Page({ params }: { params: { slug: string } }) { key: "Mainnet", value: ( <> - {keyStaticGame?.links.mainnet && ( + {keyStaticGame.links.mainnet && ( )} @@ -182,9 +183,9 @@ export default async function Page({ params }: { params: { slug: string } }) { key: "Testnet", value: ( <> - {keyStaticGame?.links.testnet && ( + {keyStaticGame.links.testnet && ( )} @@ -194,11 +195,11 @@ export default async function Page({ params }: { params: { slug: string } }) { key: "Homepage", value: ( <> - {keyStaticGame?.links.homepage && ( + {keyStaticGame.links.homepage && ( )} @@ -208,7 +209,7 @@ export default async function Page({ params }: { params: { slug: string } }) { ]; return ( -
+
@@ -223,101 +224,98 @@ export default async function Page({ params }: { params: { slug: string } }) {
-

{keyStaticGame?.title}

+

{keyStaticGame.title}

- {StatusDot(keyStaticGame?.status)} - {keyStaticGame?.status} + {StatusDot(keyStaticGame.status)} + {keyStaticGame.status}
+
+
+ {keyStaticGame.screenshots.length && ( + + + {list.map((image, index) => ( + + + + ))} + + + + + )} +
- {keyStaticGame && ( - <> -
- {keyStaticGame.screenshots.length && ( - - - {list.map((image, index) => ( - - - - ))} - - - - - )} +
+
+
-
-
- -
- -
- {keyStaticGame?.playable && keyStaticGame?.links.homepage && ( - - )} - -
- {tableData.map((data, index) => ( - - - - - ))} -
- {data.key} - - {data.value} -
-
+
+ {keyStaticGame.playable && keyStaticGame.links.homepage && ( + + )} - - - {tabs.map((tab, index) => ( - - {tab.name} - - ))} - + + {tableData.map((data, index) => ( + + + + + ))} +
+ {data.key} + + {data.value} +
+
+ + {tabs.map((tab, index) => ( - - {tab.content} - + + {tab.name} + ))} - -
- - )} + + + {tabs.map((tab, index) => ( + + {tab.content} + + ))} + +
+
); diff --git a/apps/nextjs/src/app/(app)/layout.tsx b/apps/nextjs/src/app/(app)/layout.tsx index 2c1ee416..8555a703 100644 --- a/apps/nextjs/src/app/(app)/layout.tsx +++ b/apps/nextjs/src/app/(app)/layout.tsx @@ -45,10 +45,11 @@ const backgroundImageStyle = { backgroundOpacity: 0.1, }; -const getHeaders = cache(() => Promise.resolve(headers())); +const getHeaders = cache(async() => Promise.resolve(await headers())); -export default function Layout(props: { children: React.ReactNode }) { - const { isEnabled } = draftMode(); +export default async function Layout(props: { children: React.ReactNode }) { + const { isEnabled } = await draftMode(); + const cookieStore = await cookies() return ( @@ -70,7 +71,7 @@ export default function Layout(props: { children: React.ReactNode }) { {props.children} {isEnabled && ( - Draft mode ({cookies().get("ks-branch")?.value}){" "} + Draft mode ({cookieStore.get("ks-branch")?.value}){" "}
diff --git a/apps/nextjs/src/app/(app)/page.tsx b/apps/nextjs/src/app/(app)/page.tsx index 09de0295..c3125bf0 100644 --- a/apps/nextjs/src/app/(app)/page.tsx +++ b/apps/nextjs/src/app/(app)/page.tsx @@ -1,7 +1,8 @@ +import Image from "next/image"; import Link from "next/link"; import { GameCard } from "@/app/(app)/games/GameCard"; +import { reader } from "@/utils/keystatic"; import { Button } from "@realms-world/ui/components/ui/button"; - import { Carousel, CarouselContent, @@ -15,8 +16,6 @@ import { Partners } from "../_components/Partners"; import { BlogGrid } from "./blogs/BlogGrid"; import CollectionsList from "./collection/CollectionsList"; import { EventGrid } from "./events/EventGrid"; -import Image from "next/image"; -import { reader } from "@/utils/keystatic"; export default async function Home() { const games = await reader().collections.games.all(); @@ -24,7 +23,7 @@ export default async function Home() { .filter((a) => a.entry.status === "beta" || a.entry.status === "mainnet") .map((game) => ({ alt: game.entry.title, - src: `/content/games/${game.slug}/${game?.entry.coverImage}`, + src: `/content/games/${game.slug}/${game.entry.coverImage}`, description: game.entry.description, href: `/games/${game.slug}`, title: game.entry.title, diff --git a/apps/nextjs/src/app/(app)/preview/end/route.tsx b/apps/nextjs/src/app/(app)/preview/end/route.tsx index 3be5e042..bc416440 100644 --- a/apps/nextjs/src/app/(app)/preview/end/route.tsx +++ b/apps/nextjs/src/app/(app)/preview/end/route.tsx @@ -1,6 +1,7 @@ import { cookies, draftMode } from "next/headers"; -export function POST(req: Request) { +export async function POST(req: Request) { + if (req.headers.get("origin") !== new URL(req.url).origin) { return new Response("Invalid origin", { status: 400 }); } @@ -8,7 +9,7 @@ export function POST(req: Request) { if (!referrer) { return new Response("Missing Referer", { status: 400 }); } - draftMode().disable(); - cookies().delete("ks-branch"); + (await draftMode()).disable(); + (await cookies()).delete("ks-branch"); return Response.redirect(referrer, 303); } diff --git a/apps/nextjs/src/app/(app)/preview/start/route.tsx b/apps/nextjs/src/app/(app)/preview/start/route.tsx index 5630f449..0d0a204c 100644 --- a/apps/nextjs/src/app/(app)/preview/start/route.tsx +++ b/apps/nextjs/src/app/(app)/preview/start/route.tsx @@ -11,8 +11,8 @@ export async function GET(req: Request) { if (!branch || !to) { return new Response("Missing branch or to params", { status: 400 }); } - draftMode().enable(); - cookies().set("ks-branch", branch); + (await draftMode()).enable(); + (await cookies()).set("ks-branch", branch); const toUrl = new URL(to, url.origin); toUrl.protocol = url.protocol; toUrl.host = url.host; diff --git a/apps/nextjs/src/app/(app)/studios/[slug]/page.tsx b/apps/nextjs/src/app/(app)/studios/[slug]/page.tsx index 1e6aba05..72ad2817 100644 --- a/apps/nextjs/src/app/(app)/studios/[slug]/page.tsx +++ b/apps/nextjs/src/app/(app)/studios/[slug]/page.tsx @@ -16,11 +16,12 @@ import { } from "@realms-world/ui/components/ui/tabs"; import { Button } from "@realms-world/ui/components/ui/button"; -export async function generateMetadata({ - params, -}: { - params: { slug: string }; -}): Promise { +export async function generateMetadata( + props: { + params: Promise<{ slug: string }>; + } +): Promise { + const params = await props.params; let studio = await reader().collections.studios.read(params.slug); return { title: `${studio?.title}`, @@ -31,7 +32,8 @@ export async function generateMetadata({ }, }; } -export default async function Page({ params }: { params: { slug: string } }) { +export default async function Page(props: { params: Promise<{ slug: string }> }) { + const params = await props.params; const studio = await reader().collections.studios.read(params.slug); if (!studio) return; diff --git a/apps/nextjs/src/app/(app)/user/UserTabs.tsx b/apps/nextjs/src/app/(app)/user/UserTabs.tsx deleted file mode 100644 index d8757780..00000000 --- a/apps/nextjs/src/app/(app)/user/UserTabs.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { /*hexToNumber,*/ isStarknetAddress } from "@/utils/utils"; -import { isAddress } from "viem"; - -import { NavLink } from "@realms-world/ui/components/ui/nav-link"; - -export const UserTabs = ({ address }: { address: string }) => { - const isL2 = isStarknetAddress(address); - - const isL1 = isAddress(address); - - const tabs = []; - if (isL1) { - tabs.push( - { - name: "Realms", - link: "", - }, - { - name: "Activity", - link: "activity", - }, - ); - } - if (isL2) { - tabs.push( - { name: "Golden Token", link: "" }, - { name: "Beasts", link: "beasts" }, - { name: "Blobert", link: "blobert" }, - { name: "Banners", link: "banners" }, - ); - } - return ( -
- {tabs.map((tab) => ( - - {tab.name} - - ))} -
- ); -}; diff --git a/apps/nextjs/src/app/(app)/user/WalletHeader.tsx b/apps/nextjs/src/app/(app)/user/WalletHeader.tsx new file mode 100644 index 00000000..ff230abc --- /dev/null +++ b/apps/nextjs/src/app/(app)/user/WalletHeader.tsx @@ -0,0 +1,44 @@ +"use client"; + +import { CopyButton } from "@/app/_components/CopyButton"; +import { shortenHex } from "@/utils/utils"; +import { useStarkProfile } from "@starknet-react/core"; + +interface WalletHeaderProps { + walletAddress: string; +} + +export default function WalletHeader({ walletAddress }: WalletHeaderProps) { + const { data: starkProfile } = useStarkProfile({ + address: walletAddress as `0x${string}`, + }); + + return ( +
+
+ {/**/} +
+
+

+ {starkProfile?.name ?? shortenHex(walletAddress, 10)} +

+
+ +
+
+ + {starkProfile?.name !== undefined && ( +
+

+ {shortenHex(walletAddress)} +

+
+ )} +
+
+
+ ); +} diff --git a/apps/nextjs/src/app/(app)/user/[address]/UserTokenCard.tsx b/apps/nextjs/src/app/(app)/user/[address]/UserTokenCard.tsx deleted file mode 100644 index 3e263681..00000000 --- a/apps/nextjs/src/app/(app)/user/[address]/UserTokenCard.tsx +++ /dev/null @@ -1,69 +0,0 @@ -"use client"; - -import type { paths } from "@reservoir0x/reservoir-sdk"; -import Image from "next/image"; -import Link from "next/link"; -import { AnimatedMap } from "@/app/_components/AnimatedMap"; - -import { Button } from "@realms-world/ui/components/ui/button"; -import { cn } from "@realms-world/utils"; - -function UserTokenCard({ - token, - selected, - onClick, -}: { - token: NonNullable< - paths["/users/{user}/tokens/v10"]["get"]["responses"]["200"]["schema"]["tokens"] - >[0]; - selected?: boolean; - onClick?: () => void; -}) { - return ( - - -
-
-
- - ); -} - -export default UserTokenCard; diff --git a/apps/nextjs/src/app/(app)/user/[address]/UserTokenGrid.tsx b/apps/nextjs/src/app/(app)/user/[address]/UserTokenGrid.tsx deleted file mode 100644 index 9b0b86c2..00000000 --- a/apps/nextjs/src/app/(app)/user/[address]/UserTokenGrid.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Suspense } from "react"; -import { LoadingSkeletonGrid } from "@/app/_components/LoadingSkeletonGrid"; -import { getUser } from "@/lib/reservoir/getUser"; - -import UserTokenCard from "./UserTokenCard"; - -async function UserTokenGrid({ - address, - continuation, -}: { - address: string; - continuation: string | undefined; -}) { - const { tokens, continuation: dataContinuation } = await getUser({ - address, - continuation, - }); - - return ( - <> -
- {tokens?.map((token) => ( - - ))} -
- {dataContinuation && ( - }> - - - )} - - ); -} - -export default UserTokenGrid; diff --git a/apps/nextjs/src/app/(app)/user/[address]/activity/page.tsx b/apps/nextjs/src/app/(app)/user/[address]/activity/page.tsx index efe14496..70064a32 100644 --- a/apps/nextjs/src/app/(app)/user/[address]/activity/page.tsx +++ b/apps/nextjs/src/app/(app)/user/[address]/activity/page.tsx @@ -4,22 +4,24 @@ import type { Metadata } from "next"; import { ActivityCard } from "@/app/(app)/collection/[id]/(list)/activity/ActivityCard"; import { getUsersActivity } from "@/lib/reservoir/getUsersActivity"; -export function generateMetadata({ - params, -}: { - params: { address: string }; -}): Metadata { +export async function generateMetadata( + props: { + params: Promise<{ address: string }>; + } +): Promise { + const params = await props.params; return { title: `Atlas - Collections Profile: ${params.address}`, description: `Collection Details page for ${params.address} - Created for Adventurers by Bibliotheca DAO`, }; } -export default async function Page({ - params, -}: { - params: { address: string }; -}) { +export default async function Page( + props: { + params: Promise<{ address: string }>; + } +) { + const params = await props.params; const { activities }: { activities: Activity[] } = await getUsersActivity({ address: params.address, }); diff --git a/apps/nextjs/src/app/(app)/user/[address]/banners/page.tsx b/apps/nextjs/src/app/(app)/user/[address]/banners/page.tsx deleted file mode 100644 index 0ed00c9f..00000000 --- a/apps/nextjs/src/app/(app)/user/[address]/banners/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Suspense } from "react"; -import { LoadingSkeletonGrid } from "@/app/_components/LoadingSkeletonGrid"; -import L2ERC721Table from "@/app/(app)/collection/[id]/(list)/L2ERC721Table"; -import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; - -import { Collections, getCollectionAddresses } from "@realms-world/constants"; - -export default function Page({ params }: { params: { address: string } }) { - const address = getCollectionAddresses(Collections.BANNERS)?.[ - SUPPORTED_L2_CHAIN_ID - ]; - return ( - }> - {address && ( - - )} - - ); -} diff --git a/apps/nextjs/src/app/(app)/user/[address]/beasts/page.tsx b/apps/nextjs/src/app/(app)/user/[address]/beasts/page.tsx deleted file mode 100644 index 68a8f807..00000000 --- a/apps/nextjs/src/app/(app)/user/[address]/beasts/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Suspense } from "react"; -import { LoadingSkeletonGrid } from "@/app/_components/LoadingSkeletonGrid"; -import L2ERC721Table from "@/app/(app)/collection/[id]/(list)/L2ERC721Table"; -import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; - -import { Collections, getCollectionAddresses } from "@realms-world/constants"; - -export default function Page({ params }: { params: { address: string } }) { - const address = getCollectionAddresses(Collections.BEASTS)?.[ - SUPPORTED_L2_CHAIN_ID - ]; - return ( - }> - {address && ( - - )} - - ); -} diff --git a/apps/nextjs/src/app/(app)/user/[address]/blobert/page.tsx b/apps/nextjs/src/app/(app)/user/[address]/blobert/page.tsx deleted file mode 100644 index 08f4ae36..00000000 --- a/apps/nextjs/src/app/(app)/user/[address]/blobert/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Suspense } from "react"; -import { LoadingSkeletonGrid } from "@/app/_components/LoadingSkeletonGrid"; -import L2ERC721Table from "@/app/(app)/collection/[id]/(list)/L2ERC721Table"; -import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; - -import { Collections, getCollectionAddresses } from "@realms-world/constants"; - -export default function Page({ params }: { params: { address: string } }) { - const address = getCollectionAddresses(Collections.BLOBERT)?.[ - SUPPORTED_L2_CHAIN_ID - ]; - return ( - }> - {address && ( - - )} - - ); -} diff --git a/apps/nextjs/src/app/(app)/user/[address]/goldenToken/page.tsx b/apps/nextjs/src/app/(app)/user/[address]/goldenToken/page.tsx deleted file mode 100644 index fd551881..00000000 --- a/apps/nextjs/src/app/(app)/user/[address]/goldenToken/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Suspense } from "react"; -import { LoadingSkeletonGrid } from "@/app/_components/LoadingSkeletonGrid"; -import L2ERC721Table from "@/app/(app)/collection/[id]/(list)/L2ERC721Table"; -import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; - -import { Collections, getCollectionAddresses } from "@realms-world/constants"; - -export default function GoldenToken({ - params, -}: { - params: { address: string }; -}) { - const address = getCollectionAddresses(Collections.GOLDEN_TOKEN)?.[ - SUPPORTED_L2_CHAIN_ID - ]; - return ( - }> - {address && ( - - )} - - ); -} diff --git a/apps/nextjs/src/app/(app)/user/[address]/layout.tsx b/apps/nextjs/src/app/(app)/user/[address]/layout.tsx index a5927f43..fb150130 100644 --- a/apps/nextjs/src/app/(app)/user/[address]/layout.tsx +++ b/apps/nextjs/src/app/(app)/user/[address]/layout.tsx @@ -1,19 +1,24 @@ import React from "react"; +import WalletHeader from "../WalletHeader"; + +export default async function UserLayout( + props: { + children: React.ReactNode; + params: Promise<{ address: string }>; + } +) { + const params = await props.params; + + const { + children + } = props; -export default function UserLayout({ - children, - params, -}: { - children: React.ReactNode; - params: { address: string }; -}) { //const isUserAddress = [l1Account, l2Account].includes(params?.address); return ( -
-
-
{children}
-
+
+ +
{children}
); } diff --git a/apps/nextjs/src/app/(app)/user/[address]/page.tsx b/apps/nextjs/src/app/(app)/user/[address]/page.tsx index c83ad237..0e65d563 100644 --- a/apps/nextjs/src/app/(app)/user/[address]/page.tsx +++ b/apps/nextjs/src/app/(app)/user/[address]/page.tsx @@ -4,35 +4,37 @@ import { SUPPORTED_L2_CHAIN_ID } from "@/constants/env"; import { isStarknetAddress } from "@/utils/utils"; import { Collections, getCollectionAddresses } from "@realms-world/constants"; +import { Portfolio } from "../../account/assets/Portfolio"; -import UserTokenGrid from "./UserTokenGrid"; - -export function generateMetadata({ - params, -}: { - params: { address: string }; -}): Metadata { +export async function generateMetadata( + props: { + params: Promise<{ address: string }>; + } +): Promise { + const params = await props.params; return { title: `${params.address}`, description: `${params.address} - Created for Adventurers by Bibliotheca DAO`, }; } -export default function Page({ params }: { params: { address: string } }) { +export default async function Page(props: { params: Promise<{ address: string }> }) { + const params = await props.params; const address = getCollectionAddresses(Collections.GOLDEN_TOKEN)?.[ SUPPORTED_L2_CHAIN_ID ]; if (isStarknetAddress(params.address) && address) { return ( - + <> + + ); } return (
- {isStarknetAddress(params.address)} - + Only Starknet Addresses supported
); } diff --git a/apps/nextjs/src/app/(app)/user/page.tsx b/apps/nextjs/src/app/(app)/user/page.tsx deleted file mode 100644 index 43dd6ddc..00000000 --- a/apps/nextjs/src/app/(app)/user/page.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Collections } from "@realms-world/constants"; - -import AssetL1CollectionPreview from "../account/assets/AssetL1CollectionPreview"; -import AssetL2CollectionPreview from "../account/assets/AssetL2CollectionPreview"; - -export default function Page() { - return ( -
- - - - - -
- ); -} diff --git a/apps/nextjs/src/app/_components/CollectionCard.tsx b/apps/nextjs/src/app/_components/CollectionCard.tsx index b9e14d7f..7235e6c3 100644 --- a/apps/nextjs/src/app/_components/CollectionCard.tsx +++ b/apps/nextjs/src/app/_components/CollectionCard.tsx @@ -1,5 +1,6 @@ import Image from "next/image"; import Link from "next/link"; +import { formatEther } from "viem"; interface Props { name: string | undefined; @@ -27,9 +28,11 @@ export const CollectionCard = ({ name, link, price, symbol, image }: Props) => {
{name}
- {/*
- {price} {symbol} -
*/} + {price ? ( +
+ {formatEther(BigInt(price))} {symbol} +
+ ) : null} ); }; diff --git a/apps/nextjs/src/app/_components/CopyButton.tsx b/apps/nextjs/src/app/_components/CopyButton.tsx index f177e891..c7626e83 100644 --- a/apps/nextjs/src/app/_components/CopyButton.tsx +++ b/apps/nextjs/src/app/_components/CopyButton.tsx @@ -3,7 +3,7 @@ import * as React from "react"; import { CheckIcon, ClipboardIcon } from "lucide-react"; -import { Button } from "@realms-world/ui/components/ui/button"; +import { Button, ButtonProps } from "@realms-world/ui/components/ui/button"; import { Tooltip, TooltipContent, diff --git a/apps/nextjs/src/app/_components/ProfilePicture.tsx b/apps/nextjs/src/app/_components/ProfilePicture.tsx new file mode 100644 index 00000000..d33c23cc --- /dev/null +++ b/apps/nextjs/src/app/_components/ProfilePicture.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { useState } from "react"; +import useBlockies from "@/hooks/useBlockies"; +import { useStarkProfile } from "@starknet-react/core"; +import { validateAndParseAddress } from "starknet"; + +interface ProfilePictureProps { + address: string; + className?: string; +} + +export default function ProfilePicture({ + address, + className, +}: ProfilePictureProps) { + const { data: starkProfile, error } = useStarkProfile({ + address, + }); + const { blockiesImageSrc } = useBlockies({ + address: validateAndParseAddress(address), + }); + const [hasImageFailed, setHasImageFailed] = useState(false); + + console.log(error); + + if ( + starkProfile?.name !== undefined && + starkProfile.profilePicture !== undefined && + !hasImageFailed + ) { + return ( + Starknet Id profile setHasImageFailed(true)} + /> + ); + } + + return Blockies; +} diff --git a/apps/nextjs/src/app/_components/SideMenu.tsx b/apps/nextjs/src/app/_components/SideMenu.tsx index 7f09fef6..9709aaff 100644 --- a/apps/nextjs/src/app/_components/SideMenu.tsx +++ b/apps/nextjs/src/app/_components/SideMenu.tsx @@ -14,6 +14,7 @@ import LordsIcon from "@/icons/lords.svg"; import RWLogo from "@/icons/rw-logo.svg"; import SideHeaderImg from "@/icons/side-header.svg"; import { Github, Newspaper, Twitter, User } from "lucide-react"; +import { cn } from "@realms-world/utils"; import { Button } from "@realms-world/ui/components/ui/button"; import { ScrollArea } from "@realms-world/ui/components/ui/scroll-area"; @@ -96,7 +97,11 @@ const Sidebar = () => { onClick={toggleSidebar} > - +
@@ -107,7 +112,7 @@ const Sidebar = () => { {menu.map((item, index) => { return ( - ) -}) -SidebarTrigger.displayName = "SidebarTrigger" + ); +}); +SidebarTrigger.displayName = "SidebarTrigger"; -const Sidebar = React.forwardRef & { asideClassname?: string }>( - ({ className, children, asideClassname }, ref) => { - const isMobile = useIsMobile() - const { open, onOpenChange } = useSidebar() +const SidebarRail = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<"button"> +>(({ className, ...props }, ref) => { + const { toggleSidebar } = useSidebar(); - const sidebar = ( -
- {children} -
- ) + return ( +