diff --git a/README.md b/README.md index 84b90ec0..4de3fa06 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,9 @@ Creators choose a 0 / 1 / 3 % trading fee that is pushed **in full** to benefici no transfer function. Proven with an adversarial fork suite against the live deployment. - **Three chains, one set of rules.** Base, Robinhood Chain and Arc (Circle's L1, where gas and quotes are USDC), same contracts; Arc runs `LaunchFactoryArc`, the same source plus a guard that refuses native-asset quotes (see `contracts/docs/LAUNCHPAD.md`). - **Any quote asset.** ETH, USDG, USDC on Arc, **TWIG** ([Twigpine](https://twigpine.com)'s token on Base: a 1:1 wrapper of GITLAWB, - wrap or unwrap any time with no fee; priced at GITLAWB's price; fees paid or burned in TWIG), **GITLAWB** ([Twigpine](https://twigpine.com)'s token, on Base and bridged 1:1 to - Robinhood Chain; priced from its Base Uniswap v4 WETH pool; fees paid or burned in GITLAWB; the Base form offers TWIG in its place), or a **tokenized stock**: Coinbase's B20 stocks on Base + wrap or unwrap any time with no fee; priced at GITLAWB's price; fees paid or burned in TWIG; no longer offered in the Base form, ahead of the planned + [token migration](https://migrate.twigpine.com), while launches already paired with it keep their badge, price and trading), **GITLAWB** ([Twigpine](https://twigpine.com)'s token, on Base and bridged 1:1 to + Robinhood Chain; priced from its Base Uniswap v4 WETH pool; fees paid or burned in GITLAWB; the Robinhood Chain form offers it), or a **tokenized stock**: Coinbase's B20 stocks on Base (every stock Coinbase lists: NVDAc, AAPLc, TSLAc, NFLXc, …, and new listings picked up from Coinbase's registry as they appear; shown in USD where Chainlink publishes an on-chain feed) and Robinhood Stock Tokens on Robinhood Chain. - **Trade in-page.** Buys and sells go straight to the Uniswap v4 pool through the Universal Router; the site never touches funds. diff --git a/app/package-lock.json b/app/package-lock.json index 905828d0..b217271a 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -18,7 +18,7 @@ "lightweight-charts": "^5.2.1", "lucide-react": "^1.42.0", "motion": "^13.2.0", - "next": "^16.3.8", + "next": "^16.4.5", "next-themes": "^0.4.6", "postgres": "^3.4.9", "react": "19.2.3", @@ -36,7 +36,7 @@ "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", - "eslint-config-next": "^16.3.8", + "eslint-config-next": "^16.4.5", "tailwindcss": "^4", "tsx": "^4.23.13", "typescript": "^5" @@ -2068,15 +2068,15 @@ } }, "node_modules/@next/env": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.8.tgz", - "integrity": "sha512-Al9zqHVV7TJv0eFuOU4U7Lvv74PTih4Ch63sk2xCIpSTkE3udFnaOcnzP2lQVymiL7yS9Cj2iClUXlR3EQ5sEw==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.4.5.tgz", + "integrity": "sha512-JwSPwpdkZL5VMl2jA/q+JI8MZdweAL3xmw5/tb9y/TLtmS0YXZnmYDzSihwk8xTj1OL+WM53gTqaj96yuLp6Xw==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.8.tgz", - "integrity": "sha512-eCR9RcLTZrVS+K3+VOhi0xMdUUGNuriCHHhU1ZoABC/QQ/Gp0OWbLKQxV2/9DkmihYdYRcQWFmZXW8M1AMUXYw==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.4.5.tgz", + "integrity": "sha512-dNmc4y4En/34tWxaBFF2tG/R9GeiRwVPf7v8Az/Pqk8FcT4Uv0ePmrZKvWBL2nFy1QprPgJW+6XjfyV6jbRV3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2117,9 +2117,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.8.tgz", - "integrity": "sha512-2JPRMh2nmQG5CiL7cXGL9AGwnPWJQ//cTtAUCT+w511QHk79SYz3LGv/pc5X643B/WEO0rvu3Yww0hqwt3kgeA==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.4.5.tgz", + "integrity": "sha512-W5TniBzWKASbNNwHZ/S/f1MxQUXU/LdjklVMWA0Ujbfl7SZnUzFls45hO0i/sF7Bx1jJBWp7WWmoQajXtX/O8A==", "cpu": [ "arm64" ], @@ -2133,9 +2133,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.8.tgz", - "integrity": "sha512-GZtCCOBKJ4leVIT/Th0llWKhD1ca92lzbQiS5R5ON9QkoiFnilFsebDae1JU2a3HWoKMEmEZWGs1AGLavVM72Q==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.4.5.tgz", + "integrity": "sha512-uWq4qkHapBDS1oFltWS4YxTb9pLHAtLNcpbuK6SmRsebLYZqpBML/j/C0op+50JYGTpZgVL/DWNt/6oWlamrrw==", "cpu": [ "x64" ], @@ -2149,9 +2149,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.8.tgz", - "integrity": "sha512-O659ygeQYqneJ1fBKMpFxIFqYkYswu8IAS1OCKK/4f3ZgJJm1dRz4fVJZRi/kLLWjnBKnebOePA4WNv+sV1pVA==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.4.5.tgz", + "integrity": "sha512-FdRcyOx5u5P51mlAqLB9EXdd8jZO5fsdHtk4BAQSkqOywCsbTNN/rmw+jO7pnmjNdAtu2AG46NzbCL2FPDrrgw==", "cpu": [ "arm64" ], @@ -2168,9 +2168,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.8.tgz", - "integrity": "sha512-dSjKSyWpzxoO1d3DIZZcP4XJcNaKeLmxQMFOiYl5vuBRMmweIqnAhty8tAmRsvTss779cK1FtYnDMj40e4TQlg==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.4.5.tgz", + "integrity": "sha512-cyvmmgtRXR8aGVT86wi9Py53IlfyCx7P2fZxuAXAoTummDnhKtUyjrMeXfapqp4qgD+gT5RqyGD/VfA16jEK7Q==", "cpu": [ "arm64" ], @@ -2187,9 +2187,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.8.tgz", - "integrity": "sha512-lbqOuz3RPRcv+o9msNsJw5x4+Y1ZwPTs6vmL6DCf7i0fZfvng/F59wyeDwqHIvV0mK//RBy/jJkZ+nCKsSMXjQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.4.5.tgz", + "integrity": "sha512-hPc+Fl+N22DAvqZHq559NmamXboOX5Lu8I5Wl0DezfrhTk1Zz21NQeYoZDmNI/NjTcrdsVxM72Fzn2lI+Q+vAw==", "cpu": [ "x64" ], @@ -2206,9 +2206,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.8.tgz", - "integrity": "sha512-+316WswI8ScVgZeUd+1KGaXkHhaYQzCjvH/05TZSpJ8zBizb1a4G7DtO7F12jcBIqMOtsz9ji1t48fmKtzqsGA==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.4.5.tgz", + "integrity": "sha512-gbACYE8IP/jlprNTpiWXHb8N9CofOzpnEwH2SrIz1dUbiJf1FbDssDupCAPeP1Taxe8mgG20sGZamJI7KFOdZw==", "cpu": [ "x64" ], @@ -2225,9 +2225,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.8.tgz", - "integrity": "sha512-ji0gd4kMYUxO+1fJBIbiBVRCjzG/lloiyCccnlebvb1ZJ5qXCPZqYg4Jl1DrrixnWNMKylzgpmMWx0yNDYXlzw==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.4.5.tgz", + "integrity": "sha512-+8gj++ZMo8H20Xh2ijjNqyFk5LPLw0AC4Fs4Tq/G94rjjQXhOjN4jgSWsWKPFsyY26hfIeemJIwKtMxOsp5GBA==", "cpu": [ "arm64" ], @@ -2241,9 +2241,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.8.tgz", - "integrity": "sha512-WcTlaKt/TWkh5kUjdJcUmB1XgZ+1c6fz4Y9fDHL73YNSdGaUWjceeWrrlwF0nv19iABYWC4iAq1oX1w4Bn0vfg==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.4.5.tgz", + "integrity": "sha512-qNZj66pYXnaWLiF9R9GUbfBdrCv7kC6TaZfIwB2KH5WPc/8pEM3nVOj8hpQhWJU8S94rlH5MPDcX15+RrgUhiw==", "cpu": [ "x64" ], @@ -4581,21 +4581,21 @@ } }, "node_modules/eslint-config-next": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.8.tgz", - "integrity": "sha512-81vovwMe6NGnoFsl0KUJWzlS+y239i3fdsxs49gSEX3pDQW2cuKy+fxUPXNkQqqx6OCPheYPtBlSufc9aZ0k+w==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.4.5.tgz", + "integrity": "sha512-mvh39zYLoNjpT5tVmf8xZu7i5lEOb5jN5cW6qD9OpeCp4GEEOeYta0Z2XyKiD0pYdlvm5/Td6Bi890maPRlIjg==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.3.8", + "@next/eslint-plugin-next": "16.4.5", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", - "eslint-plugin-react-hooks": "^7.0.0", + "eslint-plugin-react-hooks": "^7.1.0", "globals": "16.4.0", - "typescript-eslint": "^8.46.0" + "typescript-eslint": "^8.56.0" }, "peerDependencies": { "eslint": ">=9.0.0", @@ -6652,12 +6652,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/next/-/next-16.3.8.tgz", - "integrity": "sha512-U7QEZaTini6wKrb8A8hqLLqYQyCetegKjCpJOyxk642vWoMoU1x5PyZCJFvgYgiptA8xc5j/9xYlZFO7w9Sjmw==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/next/-/next-16.4.5.tgz", + "integrity": "sha512-rmdfsWosjTUO+6R0S3KokoIk6Kj0sWDRTe86tZHdqaWH/oXq/udX3/4xb+YQi7aWbyEFoglDU54kaifLCdXbBw==", "license": "MIT", "dependencies": { - "@next/env": "16.3.8", + "@next/env": "16.4.5", "@swc/helpers": "0.5.23", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", @@ -6671,15 +6671,15 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.3.8", - "@next/swc-darwin-x64": "16.3.8", - "@next/swc-linux-arm64-gnu": "16.3.8", - "@next/swc-linux-arm64-musl": "16.3.8", - "@next/swc-linux-x64-gnu": "16.3.8", - "@next/swc-linux-x64-musl": "16.3.8", - "@next/swc-win32-arm64-msvc": "16.3.8", - "@next/swc-win32-x64-msvc": "16.3.8", - "sharp": "^0.35.4" + "@next/swc-darwin-arm64": "16.4.5", + "@next/swc-darwin-x64": "16.4.5", + "@next/swc-linux-arm64-gnu": "16.4.5", + "@next/swc-linux-arm64-musl": "16.4.5", + "@next/swc-linux-x64-gnu": "16.4.5", + "@next/swc-linux-x64-musl": "16.4.5", + "@next/swc-win32-arm64-msvc": "16.4.5", + "@next/swc-win32-x64-msvc": "16.4.5", + "sharp": "^0.35.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -8619,9 +8619,9 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "devOptional": true, "license": "MIT", "funding": { diff --git a/app/package.json b/app/package.json index 9dee25df..67d0dc62 100644 --- a/app/package.json +++ b/app/package.json @@ -22,7 +22,7 @@ "lightweight-charts": "^5.2.1", "lucide-react": "^1.42.0", "motion": "^13.2.0", - "next": "^16.3.8", + "next": "^16.4.5", "next-themes": "^0.4.6", "postgres": "^3.4.9", "react": "19.2.3", @@ -40,7 +40,7 @@ "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", - "eslint-config-next": "^16.3.8", + "eslint-config-next": "^16.4.5", "tailwindcss": "^4", "tsx": "^4.23.13", "typescript": "^5" diff --git a/app/src/app/agents/page.tsx b/app/src/app/agents/page.tsx index 950fbd15..658909b7 100644 --- a/app/src/app/agents/page.tsx +++ b/app/src/app/agents/page.tsx @@ -76,7 +76,7 @@ export default function AgentsPage() {
-
quote
ETH uses address zero. For TWIG on Base (the quote the form offers there) use 0x6aC18bcf4eDE02591d4917452700ea5eaAea13c1. For GITLAWB use 0x5F980Dcfc4c0fa3911554cf5ab288ed0eb13DBa3 on Base (still recognised, badged and priced) or 0xd1b0d44E4f6ed940fcC7A9F59Bf30Daf62cCFe3D on Robinhood Chain; for USDG on Robinhood Chain, 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168. For any ERC-20 quote call findSalt(...) first so the token address sorts above the quote.
+
quote
ETH uses address zero. For GITLAWB on Robinhood Chain use 0xd1b0d44E4f6ed940fcC7A9F59Bf30Daf62cCFe3D; for USDG on Robinhood Chain, 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168. On Base, TWIG (0x6aC18bcf4eDE02591d4917452700ea5eaAea13c1) and GITLAWB (0x5F980Dcfc4c0fa3911554cf5ab288ed0eb13DBa3) are still recognised, badged and priced, but the Base form offers neither: GITLAWB left it when TWIG took its place, and TWIG left it ahead of the planned token migration. For any ERC-20 quote call findSalt(...) first so the token address sorts above the quote.
supply
0 means the default 1B supply.
startTick
Sets the opening market cap. A multiple of 200; 184200 ≈ 10 ETH FDV for 1B supply.
lpFee
In pips: 0, 10000 = 1%, or 30000 = 3%.
diff --git a/app/src/app/api/quotes/route.ts b/app/src/app/api/quotes/route.ts index 48089426..c9141cae 100644 --- a/app/src/app/api/quotes/route.ts +++ b/app/src/app/api/quotes/route.ts @@ -14,7 +14,7 @@ type StockHit = { key: "stock"; address: string; symbol: string; name: string; d /** * GET /api/quotes?chain=[&q=AAPL] → quote assets the launch form may offer on that chain: - * the fixed ones (ETH, USDG, USDC, TWIG, GITLAWB — TWIG and GITLAWB with GITLAWB's live USD) plus tokenized stocks from that chain's registry (with live USD where the stock has a price): + * the fixed ones (ETH, USDG, USDC, GITLAWB on Robinhood Chain with GITLAWB's live USD; never TWIG, which left the Base form) plus tokenized stocks from that chain's registry (with live USD where the stock has a price): * Coinbase tokenized stocks on Base, Robinhood Stock Tokens on Robinhood Chain, none on Arc. * `stocks` is one page of matches; `stocksMatched` is how many match the search in all and `stocksTotal` how many the chain's registry holds, so the form can say there are more. * Each stock's `issued` says whether any of it is in circulation: false = none yet (nobody can buy with it), null = not known (Robinhood, or no good read yet). diff --git a/app/src/app/llms.txt/route.ts b/app/src/app/llms.txt/route.ts index 6076587a..f5205792 100644 --- a/app/src/app/llms.txt/route.ts +++ b/app/src/app/llms.txt/route.ts @@ -68,7 +68,7 @@ ${verificationLine("Arc (5042)", a, [ ## What a launch does 1. deploys a fixed-supply ERC-20 (1,000,000,000; no mint/pause/blacklist/tax/owner) -2. initializes a Uniswap v4 pool quote/token (quote = ETH, TWIG on Base, GITLAWB, USDG on Robinhood Chain, USDC on Arc, USDC or WETH on Base (priced, not in the form), or a registry stock token; tick spacing 200, no hook) at the chosen start tick +2. initializes a Uniswap v4 pool quote/token (quote = ETH, GITLAWB or USDG on Robinhood Chain, USDC on Arc, or a registry stock token, all in the form; also TWIG, GITLAWB, USDC or WETH on Base, priced but not in the form; tick spacing 200, no hook) at the chosen start tick 3. mints one single-sided position holding 100% of supply to an ownerless locker (no withdraw path exists) 4. registers fee routing: lpFee 0 | 10000 (1%) | 30000 (3%) pips; recipients [] = fees burned, else {payout,bps}[] summing to 10000. Fixed forever. @@ -85,7 +85,7 @@ USDG (Robinhood, 6 dec): 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168 USDC (Arc, 6 dec): 0x3600000000000000000000000000000000000000 (also the gas token; native balance = the same USDC at 18 decimals) USDC (Base, 6 dec): 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 (Circle's; priced at $1) WETH (Base, 18 dec): 0x4200000000000000000000000000000000000006 (priced at ETH; buyers pay WETH, not ETH) -TWIG (Base, 18 dec): 0x6aC18bcf4eDE02591d4917452700ea5eaAea13c1 (Twigpine's token: 1:1 wrapper of GITLAWB, wrap/unwrap any time, no fee; the Base form's quote; priced = GITLAWB; fees paid in TWIG, burned when recipients = []) +TWIG (Base, 18 dec): 0x6aC18bcf4eDE02591d4917452700ea5eaAea13c1 (Twigpine's token: 1:1 wrapper of GITLAWB, wrap/unwrap any time, no fee; no longer offered in the Base form, launches already paired with it keep trading; priced = GITLAWB; fees paid in TWIG, burned when recipients = []) GITLAWB (Base, 18 dec): 0x5F980Dcfc4c0fa3911554cf5ab288ed0eb13DBa3 (Twigpine's token; still recognised and priced on Base; fees paid in GITLAWB, burned when recipients = []) GITLAWB (Robinhood, 18 dec): 0xd1b0d44E4f6ed940fcC7A9F59Bf30Daf62cCFe3D (LayerZero OFT of the Base token, 1:1) @@ -100,7 +100,7 @@ holder and no price move reads as dead on screeners and sits under "quiet launch ${boostSection()} ## Community pairs (${PAIR_CHAINS_TEXT}) A launch may be paired with a listed community token: the site badges it and prices it in USD from one named pool (checked against -that pool's 30-minute average). The launch form does not offer them (ETH, TWIG and stocks only): such a launch is made against the +that pool's 30-minute average). The launch form does not offer them: such a launch is made against the factory directly. The contracts accept any ERC-20 either way; an unlisted one shows as "Unlisted pair", unpriced. Each listing is checked hourly and suspended when its checks fail. - GET ${SITE_URL}/api/pairs (every pair: address, symbol, decimals, status, usd, price source) diff --git a/app/src/app/pairs/page.tsx b/app/src/app/pairs/page.tsx index 85942cc1..aea25df1 100644 --- a/app/src/app/pairs/page.tsx +++ b/app/src/app/pairs/page.tsx @@ -14,7 +14,7 @@ import { pairListingUsd } from "@/lib/launchpad/pairApply"; export const metadata = pageMetadata({ path: "/pairs", title: "Community pairs", - description: "Tokens a launch on openlaunch can be paired with besides ETH and TWIG. Each is listed after public checks, priced from one named pool and watched every hour.", + description: "Community tokens a launch on openlaunch can be paired with. Each is listed after public checks, priced from one named pool and watched every hour.", }); export const dynamic = "force-dynamic"; diff --git a/app/src/app/rules/page.tsx b/app/src/app/rules/page.tsx index e4e0c357..f9a1b987 100644 --- a/app/src/app/rules/page.tsx +++ b/app/src/app/rules/page.tsx @@ -8,6 +8,7 @@ import styles from "@/components/sections/RulesGuide.module.css"; import { launchpad } from "@/lib/launchpad/config"; import { CHAINS, CHAIN_KEYS, CHAIN_LABELS, explorerAddress } from "@/lib/chainPublic"; import { BRAND_GITHUB } from "@/lib/brand"; +import { TWIG_MIGRATE_URL } from "@/lib/launchpad/twig"; import LaunchMachine from "@/components/launchpad/LaunchMachine"; import { ChainLogo } from "@/components/launchpad/ChainLogo"; import BoostRulesEntry from "@/components/launchpad/BoostRulesEntry"; @@ -18,7 +19,7 @@ export const metadata: Metadata = pageMetadata({ path: "/rules", title: "How it const STEPS = [ { title: "Your token is deployed", description: "A plain ERC-20 with EIP-2612 permit. Fixed supply, 1 billion by default. No mint, no pause, no blacklist, no transfer tax, no owner.", value: "1B", label: "default supply" }, - { title: "A market opens", description: "A Uniswap v4 pool pairs your token with ETH, TWIG on Base, GITLAWB or USDG on Robinhood Chain, a tokenized stock (Coinbase stocks on Base, Robinhood Stock Tokens on Robinhood Chain), or USDC on Arc. No hook. The pool starts at the market cap you pick.", value: "v4", label: "Uniswap pool" }, + { title: "A market opens", description: "A Uniswap v4 pool pairs your token with ETH, GITLAWB or USDG on Robinhood Chain, a tokenized stock (Coinbase stocks on Base, Robinhood Stock Tokens on Robinhood Chain), or USDC on Arc. No hook. The pool starts at the market cap you pick.", value: "v4", label: "Uniswap pool" }, { title: "The liquidity position is locked", description: "100% of the supply goes into one single-sided position at launch. Its NFT is minted to an ownerless locker that has no function to withdraw, transfer or shrink it. Ever.", value: "100%", label: "deposited at launch" }, { title: "Fee routing is written in", description: "The trading fee you choose (0%, 1% or 3%) goes 100% to the beneficiaries you name, or is burned if you name none. Fixed at launch, unchangeable.", value: "0 / 1 / 3%", label: "your trading fee" }, ] as const; @@ -136,7 +137,7 @@ export default function RulesPage() {
Why is my token under “quiet launches”?

The home page ranks by facts, not by launch order. A token is live once a wallet other than its launcher has traded it in the last 24 hours; trades in the launch block and the next three blocks (snipe bots) don't count, and neither do the launcher's own. Live tokens rank by outside wallets in the last hour, then today, then by their last outside trade. A wallet's newest launch gets its first hour on the board regardless; after that it sits under quiet launches, one row per wallet, until someone trades it.

Nothing is hidden: every launch stays in the New tab, in search and in the API. The only way up is a trade from an outside wallet.

{boostEnabled() ? : null}
What can change after launch?

Nothing on-chain can be edited after launch: not the name, not the fee, not the beneficiaries. Metadata (image, description, links) is stored by this site and can change; the token itself cannot.

-
What is a TWIG- or GITLAWB-quoted pool?

TWIG is Twigpine's token on Base: a 1:1 wrapper of GITLAWB. Anyone can wrap GITLAWB into TWIG, or unwrap it back, at any time with no fee, and every TWIG is backed by one GITLAWB held in its contract, which has no owner and no transfer restrictions. It is the quote the Base form offers: pick it and buyers pay in TWIG; any trading fee is paid in TWIG to the beneficiaries named at launch (by their shares) when it is collected, and a launch that names none has its TWIG fees burned when they are collected.

GITLAWB is Twigpine's token on Base, bridged 1:1 to Robinhood Chain over LayerZero (one supply, two chains): an ordinary ERC-20 with no transfer restrictions and no issuer switch. The Robinhood Chain form offers it; on Base, pools already paired with GITLAWB keep their badge and price. Fees work the same way: paid in GITLAWB when collected, and a launch that names no beneficiary has its GITLAWB fees burned when they are collected.

Dollar figures for both come from the Uniswap v4 WETH/GITLAWB pool price on Base, cross-checked against a 30-minute on-chain average, and ETH/USD; one TWIG counts as one GITLAWB, since it unwraps to one. They are for display and sorting only; nothing on-chain depends on them.

+
What is a TWIG- or GITLAWB-quoted pool?

TWIG is Twigpine's token on Base: a 1:1 wrapper of GITLAWB. Anyone can wrap GITLAWB into TWIG, or unwrap it back, at any time with no fee, and every TWIG is backed by one GITLAWB held in its contract, which has no owner and no transfer restrictions. The Base form no longer offers it, ahead of the planned GITLAWB and TWIG token migration (migrate.twigpine.com). Launches already paired with TWIG keep their badge, price and trading: buyers pay in TWIG; any trading fee is paid in TWIG to the beneficiaries named at launch (by their shares) when it is collected, and a launch that names none has its TWIG fees burned when they are collected.

GITLAWB is Twigpine's token on Base, bridged 1:1 to Robinhood Chain over LayerZero (one supply, two chains): an ordinary ERC-20 with no transfer restrictions and no issuer switch. The Robinhood Chain form offers it; on Base, pools already paired with GITLAWB keep their badge and price. Fees work the same way: paid in GITLAWB when collected, and a launch that names no beneficiary has its GITLAWB fees burned when they are collected.

Dollar figures for both come from the Uniswap v4 WETH/GITLAWB pool price on Base, cross-checked against a 30-minute on-chain average, and ETH/USD; one TWIG counts as one GITLAWB, since it unwraps to one. They are for display and sorting only; nothing on-chain depends on them.

What should I know about stock-quoted pools?

Stock-quoted pools use tokenized stocks as the quote asset: Coinbase tokenized stocks (B20) on Base, recognised here only from Coinbase's official list and priced in dollars where Chainlink publishes an on-chain feed (the others show no dollar price); Robinhood Stock Tokens on Robinhood Chain, recognised only from Robinhood's own registry.

Both are securities issued by third parties under Regulation S and are not offered to US persons. Coinbase's also exclude the UK, Canada, Australia, Singapore and Switzerland. Their issuers can pause transfers or freeze wallets in restricted jurisdictions. Holding or trading them is subject to the issuer's terms, not ours.

diff --git a/app/src/components/launchpad/ChainLanding.tsx b/app/src/components/launchpad/ChainLanding.tsx index d0937961..41b9a91b 100644 --- a/app/src/components/launchpad/ChainLanding.tsx +++ b/app/src/components/launchpad/ChainLanding.tsx @@ -12,7 +12,7 @@ import shell from "@/components/sections/SectionShell.module.css"; import { CHAIN_KEYS, CHAIN_LABELS, CHAINS, EXPLORERS, explorerAddress, type ChainKey } from "@/lib/chainPublic"; import { BRAND } from "@/lib/brand"; import { CHAIN_LANDING, chainLandingPath } from "@/lib/chainLanding"; -import { hasChainPage, launchpad } from "@/lib/launchpad/config"; +import { STOCK_SOURCE, hasChainPage, launchpad } from "@/lib/launchpad/config"; import { getLaunchTotalsForRequest, listLaunchesPage } from "@/lib/launchpad/queries"; import { PAGE_SIZE } from "@/lib/launchpad/paging"; import { ethUsd } from "@/lib/launchpad/ethPrice"; @@ -57,7 +57,7 @@ export default async function ChainLanding({ chain }: { chain: ChainKey }) {

{CHAIN_LABELS[chain]} at a glance

- q.symbol).join(" · ")} note="What the pool trades against, picked at launch." /> + q.symbol), ...(STOCK_SOURCE[chain] ? ["Stocks"] : [])].join(" · ")} note="What the pool trades against, picked at launch." />
diff --git a/app/src/components/launchpad/LaunchForm.tsx b/app/src/components/launchpad/LaunchForm.tsx index 5157aba8..ba24b6a7 100644 --- a/app/src/components/launchpad/LaunchForm.tsx +++ b/app/src/components/launchpad/LaunchForm.tsx @@ -14,7 +14,6 @@ import FeeChip, { feeModeOf } from "./FeeChip"; import LaunchFeeSettings, { type FeeBeneficiary } from "./LaunchFeeSettings"; import { QuoteBrandBadge } from "./QuoteBadge"; import { GitlawbMark } from "./GitlawbBadge"; -import { TwigMark } from "./TwigBadge"; import { ChainLogo } from "./ChainLogo"; import { XMark } from "./BrandMarks"; import { ToggleGroup, ToggleGroupItem } from "@/components/vendor/toggle-group"; @@ -31,7 +30,7 @@ import { BUY_PRESETS, defaultFirstBuy, gasReserveInQuote, suggestFirstBuy } from import { getFirstBuyDeclined, getFirstBuyDeclinedServer, setFirstBuyDeclined, subscribeFirstBuyDeclined } from "@/lib/launchpad/first-buy-session"; import { encodeV4ExactInSingle, type PoolKey } from "@/lib/launchpad/swap"; import { GITLAWB_SITE } from "@/lib/launchpad/gitlawb"; -import { TWIG_WRAP_URL, gitlawbLinkedUsd } from "@/lib/launchpad/twig"; +import { gitlawbLinkedUsd } from "@/lib/launchpad/twig"; import { parseXHandle } from "@/lib/launchpad/xHandle"; import { CHAINS, CHAIN_LABELS, CHAIN_KEYS, DEFAULT_CHAIN, BUILDER_DATA_SUFFIX, explorerTx, shortAddr, type ChainKey } from "@/lib/chainPublic"; import { friendlyError } from "@/lib/errors"; @@ -75,8 +74,8 @@ const STOCK_PICK_MESSAGE = "Pick a stock to price the token in, or switch the qu /** Per-chain copy in the form. A chain's quotes and stock registry differ, so its sentences do too; `stock` is null where no registry exists. */ const CHAIN_COPY: Record = { base: { - blurb: "Priced in ETH, TWIG or a Coinbase tokenized stock. Gas ≈ cents.", - gitlawbOrigin: "", // the Base form offers TWIG, not GITLAWB, so this copy is never shown there + blurb: "Priced in ETH or a Coinbase tokenized stock. Gas ≈ cents.", + gitlawbOrigin: "", // the Base form offers neither GITLAWB nor TWIG, so this copy is never shown there stock: { pays: "Buyers pay with a Coinbase tokenized stock; fees are paid in that stock.", badge: "Coinbase stock", @@ -184,14 +183,15 @@ export default function LaunchForm({ ethUsd, gitlawbUsd = null, initialChain = D const [stockTotal, setStockTotal] = useState(0); // how many stocks the chain's registry holds; the list below shows one page of them const [stockMatched, setStockMatched] = useState(0); // how many match the search in all const [stockAnswered, setStockAnswered] = useState(null); // the search text the page shown answers - // GITLAWB's USD is live: the page fetched it server-side (same as ethUsd); the static config carries null. TWIG unwraps 1:1 to GITLAWB, so it takes the same price (gitlawbLinkedUsd). + // GITLAWB's USD is live: the page fetched it server-side (same as ethUsd); the static config carries null (gitlawbLinkedUsd). const staticQuote: Quote = quoteKey === "stock" && stock ? stock : (cfg.quotes.find((q) => q.key === quoteKey) ?? cfg.quotes[0]); const linkedUsd = gitlawbLinkedUsd(staticQuote.key, gitlawbUsd); const quote: Quote = linkedUsd === undefined ? staticQuote : { ...staticQuote, usd: linkedUsd }; - // the branded quote this chain's form offers, if any: TWIG on Base, GITLAWB on Robinhood Chain - const brandQuote = cfg.quotes.find((q) => q.key === "twig") ?? cfg.quotes.find((q) => q.key === "gitlawb") ?? null; - // TWIG and GITLAWB: badged, priced at GITLAWB's live price, millions of units per dollar - const isBrandQuote = quote.key === "twig" || quote.key === "gitlawb"; + // the branded quote this chain's form offers, if any: GITLAWB on Robinhood Chain. Never TWIG: it left the Base form + // for the token migration, and launches already paired with it keep their badge everywhere else on the site. + const brandQuote = cfg.quotes.find((q) => q.key === "gitlawb") ?? null; + // GITLAWB: badged, priced at its live price, millions of units per dollar + const isBrandQuote = quote.key === "gitlawb"; const quoteUsd = quoteUsdOf(quote, ethUsd); const NATIVE_SYMBOL = CHAIN.nativeCurrency.symbol; const gasReserve = GAS_RESERVE_WEI[chain]; @@ -292,7 +292,7 @@ export default function LaunchForm({ ethUsd, gitlawbUsd = null, initialChain = D const initialBuy = typedBuy || suggestion.amount || ""; const buySource: "typed" | "suggested" | "none" = typedBuy ? "typed" : suggestion.amount ? "suggested" : "none"; const initialBuyRaw = parseBuyAmount(initialBuy, quote.decimals); - // "1,000,000 TWIG", not "1000000 TWIG": every digit of what the buy will send, grouped (never rounded, it is what the creator confirms) + // "1,000,000 GITLAWB", not "1000000 GITLAWB": every digit of what the buy will send, grouped (never rounded, it is what the creator confirms) const initialBuyLabel = initialBuyRaw ? `${fmtUnitsExact(initialBuyRaw, quote.decimals)} ${quote.symbol}` : ""; const errors: string[] = []; // the token step's checks, named once: the validation list and the step rail both read them @@ -553,7 +553,7 @@ export default function LaunchForm({ ethUsd, gitlawbUsd = null, initialChain = D ); })} - {/* every chain offers at least one fixed quote plus tokenized stocks; Base also offers TWIG, Robinhood Chain GITLAWB */} + {/* every chain offers at least one fixed quote; Base and Robinhood Chain add tokenized stocks, Robinhood Chain GITLAWB */} {cfg.quotes.length > 0 ? (
@@ -591,12 +591,8 @@ export default function LaunchForm({ ethUsd, gitlawbUsd = null, initialChain = D

Your token carries the badge on the launch list, trending, the activity feed, its page and its share card.{" "} - {quote.key === "twig" ? ( - <>TWIG is Twigpine's token on Base: a 1:1 wrapper of GITLAWB that anyone can wrap or unwrap any time, with no fee. No owner, no transfer restrictions. Name no beneficiary and the fees are burned as TWIG when collected. Priced at GITLAWB's price, from the Uniswap v4 WETH/GITLAWB pool on Base. - ) : ( - <>GITLAWB is Twigpine's token{CHAIN_COPY[chain].gitlawbOrigin}: an ordinary ERC-20, no transfer restrictions, no issuer switch. Name no beneficiary and the fees are burned as GITLAWB when collected. Price from the Uniswap v4 WETH/GITLAWB pool on Base. - )}{" "} - {quote.key === "twig" ? "wrap.twigpine.com" : "twigpine.com"} ↗ + GITLAWB is Twigpine's token{CHAIN_COPY[chain].gitlawbOrigin}: an ordinary ERC-20, no transfer restrictions, no issuer switch. Name no beneficiary and the fees are burned as GITLAWB when collected. Price from the Uniswap v4 WETH/GITLAWB pool on Base.{" "} + twigpine.com ↗

) : null} @@ -1058,7 +1054,6 @@ function Step({ n, done, last = false, icon, children }: { n: number; done: bool /** A quote's mark in the picker: the bundled logo where there is one, a plain glyph for the rest. */ function QuoteMark({ k }: { k: Quote["key"] }) { - if (k === "twig") return ; if (k === "gitlawb") return ; if (k === "stock") return