diff --git a/package-lock.json b/package-lock.json index cc0f7f9..02210e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,9 +15,12 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", + "markdown-to-jsx": "^7.1.7", "react": "^18.2.0", "react-dom": "^18.2.0", "react-helmet-async": "^1.3.0", + "react-query": "^3.39.2", + "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", "web-vitals": "^3.0.0" } @@ -3147,6 +3150,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.2.tgz", + "integrity": "sha512-GRSOFhJzjGN+d4sKHTMSvNeUPoZiDHWmRnXfzaxrqe7dE/Nzlc8BiMSJdLDESZlndM7jIUrZ/F4yWqVYlI0rwQ==", + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -5330,6 +5341,14 @@ "node": ">= 8.0.0" } }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -5442,6 +5461,21 @@ "node": ">=8" } }, + "node_modules/broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -11414,6 +11448,11 @@ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==" }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -11760,6 +11799,26 @@ "tmpl": "1.0.5" } }, + "node_modules/markdown-to-jsx": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz", + "integrity": "sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==", + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/match-sorter": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", + "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "remove-accents": "0.4.2" + } + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -11822,6 +11881,11 @@ "node": ">=8.6" } }, + "node_modules/microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -11987,6 +12051,14 @@ "multicast-dns": "cli.js" } }, + "node_modules/nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "dependencies": { + "big-integer": "^1.6.16" + } + }, "node_modules/nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -12235,6 +12307,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -14216,6 +14293,31 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-query": { + "version": "3.39.2", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.2.tgz", + "integrity": "sha512-F6hYDKyNgDQfQOuR1Rsp3VRzJnWHx6aRnnIZHMNGGgbL3SBgpZTDg8MQwmxOgpCAoqZJA+JSNCydF1xGJqKOCA==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -14224,6 +14326,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.2.tgz", + "integrity": "sha512-Rb0BAX9KHhVzT1OKhMvCDMw776aTYM0DtkxqUBP8dNBom3mPXlfNs76JNGK8wKJ1IZEY1+WGj+cvZxHVk/GiKw==", + "dependencies": { + "@remix-run/router": "1.0.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.2.tgz", + "integrity": "sha512-yM1kjoTkpfjgczPrcyWrp+OuQMyB1WleICiiGfstnQYo/S8hPEEnVjr/RdmlH6yKK4Tnj1UGXFSa7uwAtmDoLQ==", + "dependencies": { + "@remix-run/router": "1.0.2", + "react-router": "6.4.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -14460,6 +14592,11 @@ "node": ">= 0.10" } }, + "node_modules/remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -15981,6 +16118,15 @@ "node": ">= 10.0.0" } }, + "node_modules/unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "dependencies": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -19153,6 +19299,11 @@ "source-map": "^0.7.3" } }, + "@remix-run/router": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.2.tgz", + "integrity": "sha512-GRSOFhJzjGN+d4sKHTMSvNeUPoZiDHWmRnXfzaxrqe7dE/Nzlc8BiMSJdLDESZlndM7jIUrZ/F4yWqVYlI0rwQ==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -20792,6 +20943,11 @@ "tryer": "^1.0.1" } }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -20887,6 +21043,21 @@ "fill-range": "^7.0.1" } }, + "broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "requires": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, "browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -25203,6 +25374,11 @@ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==" }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -25469,6 +25645,21 @@ "tmpl": "1.0.5" } }, + "markdown-to-jsx": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz", + "integrity": "sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==", + "requires": {} + }, + "match-sorter": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", + "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", + "requires": { + "@babel/runtime": "^7.12.5", + "remove-accents": "0.4.2" + } + }, "mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -25516,6 +25707,11 @@ "picomatch": "^2.3.1" } }, + "microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -25629,6 +25825,14 @@ "thunky": "^1.0.2" } }, + "nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "requires": { + "big-integer": "^1.6.16" + } + }, "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -25799,6 +26003,11 @@ "es-abstract": "^1.19.1" } }, + "oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" + }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -27051,11 +27260,38 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-query": { + "version": "3.39.2", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.2.tgz", + "integrity": "sha512-F6hYDKyNgDQfQOuR1Rsp3VRzJnWHx6aRnnIZHMNGGgbL3SBgpZTDg8MQwmxOgpCAoqZJA+JSNCydF1xGJqKOCA==", + "requires": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.2.tgz", + "integrity": "sha512-Rb0BAX9KHhVzT1OKhMvCDMw776aTYM0DtkxqUBP8dNBom3mPXlfNs76JNGK8wKJ1IZEY1+WGj+cvZxHVk/GiKw==", + "requires": { + "@remix-run/router": "1.0.2" + } + }, + "react-router-dom": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.2.tgz", + "integrity": "sha512-yM1kjoTkpfjgczPrcyWrp+OuQMyB1WleICiiGfstnQYo/S8hPEEnVjr/RdmlH6yKK4Tnj1UGXFSa7uwAtmDoLQ==", + "requires": { + "@remix-run/router": "1.0.2", + "react-router": "6.4.2" + } + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -27238,6 +27474,11 @@ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" }, + "remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + }, "renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -28351,6 +28592,15 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, + "unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "requires": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index b8b19c1..f108ed3 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,12 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.0.0", + "markdown-to-jsx": "^7.1.7", "react": "^18.2.0", "react-dom": "^18.2.0", "react-helmet-async": "^1.3.0", + "react-query": "^3.39.2", + "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", "web-vitals": "^3.0.0" }, diff --git a/papers/subsidized-on-chain-public-goods.md b/papers/subsidized-on-chain-public-goods.md new file mode 100644 index 0000000..cd492c1 --- /dev/null +++ b/papers/subsidized-on-chain-public-goods.md @@ -0,0 +1,165 @@ +title:Subsidized On-Chain Public Goods +date:Sep. 09, 2022 +author:danner* and CHANCE+ +description: Through the use of publicly contributable vaults purpose built to pay gas on behalf of users, blockchains can fund public goods with certainty that funds will not be misappropriated and without directly enriching grantees. +--- +Through the use of publicly contributable vaults permissioned solely to pay transaction fees on behalf of users, grantors can fund public goods with certainty that funds will not be misappropriated and without directly enriching grantees. Use case specific applications surfacing highly flexible protocols and primitives may merit retroactive public goods funding from networks in which they are deployed. As highly usable and desirable implementations, these applications and protocols will be demanded by existing users and may potentially draw in new users. Vaults funded by blockchain foundations and network participants will be used to subsidize the usage of these applications. + +Historically, initiatives have required the raising of funds to design, produce, and distribute a product. In Web2, this was often through venture capitalists who acquired equity in the initiative and sought to profit from it. In Web3, we have seen a wider variety of funding models – with outcome based desires that vary from traditional private equity models. + +Throughout 2021 and 2022, the blockchain industry has operated based on a diversified capital stack composed of venture capitalists, professional and amateur market makers, speculative retail traders, and treasury grant issuance. While much of that capital stack is familiar, treasury grant issuance is nuanced and accounts for a large amount of the capital directed towards those who create value for the network. + +One of the most admirable and fascinating types of treasury grant issuance is retroactive public goods funding. Optimism has been a leader in this space. Retroactive public goods funding is the idea that grant distribution is made easier by rewarding what was useful rather than what might be useful. + +One of the more interesting uses of capital has been to subsidize the costs of on-chain transaction fees for users. DAO tools, NFT product lines, etc; developers and businesses have found ways to improve end user experience by paying their fees for them. In traditional businesses, this may be viewed as a cost of customer acquisition and is often a teaser rate. While we have not seen crypto companies adjust their models yet, we must recognize that at scale, paying transaction fees on behalf of all users is not a maximal or even sustainable business model. + +The Badge Bound Pay Master primitive empowers subsidization of any on-chain product line. + +## Full Spectrum Funding in Web3 + +Optimism has made a commitment to fund the first public goods exit. With their focus on retroactive public goods funding, they wish to scour the market for teams and products that have created value for the wider network and to reward these teams. + +Critically, retroactive public goods funding requires that the good has already created value. + +While some developers may pursue retroactive public goods funding upon adoption, they may still need to raise up front capital required to develop and distribute their product. + +Through a combination of venture capital and retroactive funding, developers may access capital at the beginning and end of their journey. As noted above, a portion of raised capital is often utilized by businesses to support the subsidization of transaction fees throughout the development and distribution of the product. + +With the introduction of Badge Bound Pay Masters, developers can access capital solely for the purpose of subsidizing on-chain transactions associated with their product. For the first time, money can be publicly raised for the sole purpose of on-chain operational overhead. + +1. Private capital may be raised to develop, deploy, and market via venture, grants, etc. +2. Public funding can be accessed to ease user adoption via Badge Bound Pay Masters. +3. Public funding may be accessed via retroactive public goods funding + +Badge Bound Pay Masters may be utilized by for profit and non-profit teams depending on their unique goals and circumstances. This paper makes no claims about the feasibility of accessing various capital stacks but does assert that this new conduit creates a value flow from grantors to users and grantees without directly enriching grantees. + +## Delegated Transaction Execution + +The Flow blockchain has been a leader in crypto consumer products. From CryptoKitties to NFL All Day and everything in between, Dapper has focused on end user experience from the beginning. One of the critical features of Dapper products on Flow is that all chain transaction fees are abstracted away from the end user. This experience is far superior and drives widespread adoption but we have not seen it fully penetrate the EVM user experience. + +Over the past year, a number of DAO tools have begun to adopt delegated calls that allow them to subsidize transactions for users. For example, MetricsDAO and other organizations use Utopia and Parcel to process transactions from the multisig without the need to pay gas costs. By offering this service, these tooling organizations are able to drive adoption at a much higher rate. + +- Subsidization implementation +- Flashbots ? +- Transaction bundling ? + +## Badge Bound Pay Masters + +Through the introduction of a public funding address to support subsidization of gas costs for a protocol alongside permissioned access to those funds, development teams can flexibly deploy product lines with distinct and secure user subsidization mechanisms. In addition to the design space that this provides to developers, implementers, and operators, Badge Bound Pay Masters allow grantors to maintain public insight into the use of their funds and to trust that funds will not be used improperly. + + +- Implementation details + +A public address that can accept funds from anyone and may be deployed towards permissionlessly created targets is ripe for exploitation. For example, someone may set up many Safes with Parcel and begin to run excessive transactions. Through this exploit path, a malicious actor may drain a protocol bound pay master. + +Badge Bound Pay Masters allows for much more sophisticated pay master binding structures. + +Rather than being relegated to a single vault for a product. Implementers may use Badges to represent which addresses may utilize the Badge Bound Pay Master. Issuance and revoking of Badges for any given pay master may be manually or programmatically managed. + +Products that currently subsidize for all users may introduce freemium or VIP tiers that are managed manually or through any number of automated strategies. Examples and potential implications of various multi-dimensional subsidization models are explored below. + +## Application Driven Value Creation & Grant Based Funding + +Primitives and protocols are valuable due to the applications that expose them to users. Applications may have multiple product lines that they offer to their users. These products may range from free to paid and may access different aspects of the capital spectrum. Historically, raising venture capital and accessing public funding via grants has been blurry and contentious and accessing venture capital and public goods funding simultaneously has been nearly impossible. + +With the flexibility provided by product line specific Badge Bound Pay Masters, capital can be directed by any party (public or private) with high certainty that it will be used to subsidize transaction costs. Grant programs have struggled to follow the trail of funds and to attribute specific outcomes to them. With on-chain vaults purely permissioned to subsidize transaction fees, this problem does not apply. + +There are grantors who wish only to subsidize product lines that meet their criteria, investors who wish to manage on-chain operational costs independently of equity positions, good samaritans who wish to make a product more accessible to others, etc. This type of financial management is now possible. + +Due to the public nature of funds transfers and usage of on-chain vaults, following the money has never been easier. Furthermore, usage stats and costs can be easily tracked, accounted for, and projected. Funding request amounts can be supported by historical data and can be constantly monitored. + +## Multi-Dimensional Subsidization Rates + +A number of heuristics may be used to determine subsidization multipliers. These heuristics may be independently configured, layered, and aggregated depending on the desired outcome. At this stage, aspects of this remain conceptual – but the primitive are fully implementable. + +Dimensions and the intersection of those covered here is not comprehensive. + +### Usage Metrics + +Products may track metrics related to their users and manage subsidies based on usage. + +1. Power User Incentives + +![](https://lh6.googleusercontent.com/FEv48znZlvnZolvKu3G6psoouXy81zhSI04-AXGuVAv7zEmqzzHgFtPW7cO07Dz2WJfldWZjJ4zzCU5Bs8STsLlb_kXJBKSriZTNU80T8bslNRMQmDisRQYC24dOqmJR60w4MUhLlTaHAKMtj4TdEe972orfdIMKluBiFyAJBy1usXaDmAGSXEMTZQ) + +Products may wish to subsidize transactions for their heaviest users. This rewards power users and creates an incentive mechanism that may increase adoption as users unlock more free access as they pay over time. + +2. Teaser Rates + +![](https://lh6.googleusercontent.com/L9nL90U0dco_9q3XbbQDFgvrVF6b0sgge8j00Syod3GWD-w_2oF5tB0_dXJZFyPQIDUoHTU4X8bOuhRTOFQkSEdbtfmwW3wd1yo22asy24ENM4HtK-YYjgKo0nCMGKq7D-h2CrVOpjMR6Wq39QMyEx7OpbB6eiAwKty9CSg5HgIA1lbsUWF38n7JDA) + +Products may wish to subsidize transaction fees for new users and then to increase costs over time. This is most similar to models seen on credit card interest rates, ISP/cell provider changes, etc. New users get hooked and then need to pay for access as they increase usage. + +3. Dunning Kreuger + +![](https://lh4.googleusercontent.com/21VDiG9r9ll6n3kTx4sGhRrHAlDpYN6ZTg462c9NnmRBJFI4IwqgD_9oWaTpsJkluyvLyj9bzw8vkJ3CQaThG4K7VW09Z-N5F3yWt90wYwBaIpCdgYZRBjPVEZA9eZH4_fIedLjQi95SjeiIlP3nyIqGjEVtzflT0v4B6RjJG9HBI-ogkSxV8INgtA) + +Products may wish to ease early adoption before adding friction that is removed once the user becomes more active with the product. This could create situations of quick adoption and then ongoing subsidization to users who engage heavily with the product. + +### Subsidization Vault Depth + +Products may adjust the level of subsidization they are willing to provide based on the depth of funds available for subsidies. Combined with the Curve Registry, vault depth heuristics may be extremely flexible. The below describes general structures, but not the values of the variables required to create the curve. + +1. Altruistic Alignment + +![](https://lh5.googleusercontent.com/LdqNoJwz53HBRKAJre1K3Lef1NGMuXBBykClLSe7-Iw0xKFzQTn-SW8P2ogK7hGnET6CXvDzgX_cWlQhNnUEa75y57F5txyBoIxBCechA0yzG-8d5DqZ0ASPsACHc8YB1S2ywN_mm0q40ETbg4qYYH74wSmUi7UETLQCw9QRBmFwirQjMqGKSzsSEg) + +Products may wish to allow transactions to flow freely when there is great depth and for transactions to receive less subsidization when there is lower depth. As funds decrease and subsidization decreases, it benefits all users to add funds to the vault. + +2. Cornucopia Deployment + +![](https://lh4.googleusercontent.com/SBCXev9iAhQ_ifQ6UfCuMmi8XyxWMqZarZ9lBynYOh-VzvPOc3St1nRQuHLsJZo3LJVh7BqPjZBsXNVKUE10vyR3t0SJP-eTjPBMPF5y0j7CBzgevyojIlvEHPicOTCeBzIw6NeqtQwjpknmxCemhBgnaF3jErItNnRypNP4KZyybBzs4eRkJ20Kbw) + +Products may wish to issue subsidization consistently, regardless of vault depth. In this case, the curve is flat and funds are simply drawn down. Funds may be added but the subsidization rate is not impacted by vault depth. This creates a scenario in which users are incentivized to use what exists before it disappears without regard for their impact on others. + +3. Sisyphus Friction + +![](https://lh6.googleusercontent.com/LA30IHqhdvL2F2lRbTGARWSTCuJza6s42sdZaZKzb5DFQ_aq3muBzcWe07N1kzunl7F2Bb63ujpeFM0nPWaAJyXhCk6tVp90piGk80-_Tr-cYYbqMivcHxQ5hVN1Ob_ZCzGBT3OnyJyyZZf0A6hMP_YO5fwX5RovVRFVf3iVCoYyO9swSoe9RPsvvA) + +Products may wish to slow the subsidization of a feature line. In this case, a curve that lowers the subsidization multiplier may be used. As funds are added to the vault, the usage of features increases. + +4. Dunning Kreuger + +![](https://lh6.googleusercontent.com/p32Wzu9l6603GABcuRHuAObfQx7wITTQKn-p9mnwWCFiVVpKWqyuDbSMw92s_khU7sjYjp4iAHCdqcb3AMyPFDbLOlfYyouDcUJT_EzUX-mjd57vxIgdQldrjdzJ7aOPSMtNXq_YFD2KGyHtmjgRZ47MgE6ZVuFv6pjkGIBS9YAFvi7xkg5PH-9s1A) + +Products may wish to ease early adoption before adding friction that is removed once the user becomes more active with the product. This could create situations of quick adoption and then ongoing rewards to user + +### Managed Tiers + +Products may wish to add a layer of tiers that can be applied programmatically or manually. If a user meets certain criteria, they may immediately fall into a specific category. If a user pays for increased tiering, they may receive a special multiplier. + +While this covers a range of the heuristics that could be used to determine subsidization rates for distinct users, the level of flexibility in this space is highly underexplored and due to the composable nature of these primitives, implementers may add new heuristics or determine new intersectional layering that is best suited for their environment. + +### Cross Chain Presence + +As the EVM ecosystem has flourished, contracts have suffered from the reality that they do not share the same public key on all networks. While externally owned accounts (EOAs) benefit from the same public key on all chains, contracts can only achieve this if deployed using Create2. + +As the historical leader in EVM multisig solutions, Safe has implemented Create2 optionality but has not exposed it on the front end. Due to the lack of understanding around this functionality, [Wintermute lost 20m OP](https://cryptobriefing.com/wintermute-makes-optimistic-assumption-loses-20m-optimism-tokens/) ($15m USD) by providing their Ethereum Safe address without ensuring that they had the same public address on the Optimism network. Widespread implementation of Create2 will stop these types of errors from occurring in the future. + +Organizations are already beginning to propagate across multiple chains. In the past, a DAO or token network may have been limited to one chain. In the future, token networks will exist across many chains. Protocols that are available on all chains empower developers, users, and operators to utilize the tools they want, where they want them. + +## Use Case 1: Subsidized Organization Management with Badger + +As the premiere key issuer for on-chain organizations, Badger allows you to manage group policies on-chain with a flexible ERC-1155 minter and a purpose built application. At its core, Badger is a public good that anyone can use to create an on-chain organization or launch a DAO. Badger may be utilized by for profit companies, DAOs, schools, etc. It is + +An EVM chain such as Optimism that wants to support the growth of DAO’s in its ecosystem may fund a Badge Bound Pay Master. This vault could be limited to transactions on the Optimism chain and may even be limited to a select category or organizations as determined by a committee or through programmatic means. + +Organization operators that meet the criteria determined by Optimism receive a Badge that gives them access to the badge bound vault. Through this mechanism, Optimism can reduce friction for operators who want to launch and/or manage their DAO with Badger. + +While the transaction costs to deploy an organization using Badger on Optimism may seem inconsequential to some, these costs may be inordinate to others. Through permissioned subsidization of these costs, the launching of on-chain organizations can be made more equitable. + +## Use Case 2: Subsidized Participant Payments for MetricsDAO + +MetricsDAO runs on-demand analytics services facilitated through labor markets and makes payments on multiple EVM chains to the analyst and subsidizes payments in its network. To maximize user experience, MetricsDAO subsidies payments for its participants. This requires making hundreds if not thousands of payments monthly which adds up, especially on more expensive networks such as ethereum. + +By introducing a Badge Bound Pay Master that accepts public funding and is permissioned for use by MetricsDAO’s protocol, participants subsidized payment flows can be supported by MetricsDAO, its stakeholders, and any grantors who wish to support the MetricsDAO mission in a straightforward and measurable way. + +**References:** + +[https://medium.com/ethereum-optimism/retroactive-public-goods-funding-33c9b7d00f0c](https://medium.com/ethereum-optimism/retroactive-public-goods-funding-33c9b7d00f0c) + +[https://docs.trybadger.com/](https://docs.trybadger.com/) + +[https://github.com/FlipsideCrypto/badger/pull/122](https://github.com/FlipsideCrypto/badger/pull/122) + +Curve Registry (unpublished) \ No newline at end of file diff --git a/public/index.html b/public/index.html index 3d6f2c7..d68576b 100644 --- a/public/index.html +++ b/public/index.html @@ -5,10 +5,6 @@ - diff --git a/public/papers-cdn/Usage_-_Dunning.png b/public/papers-cdn/Usage_-_Dunning.png new file mode 100644 index 0000000..010eade Binary files /dev/null and b/public/papers-cdn/Usage_-_Dunning.png differ diff --git a/src/App.css b/src/App.css index 76329a7..2b7df03 100644 --- a/src/App.css +++ b/src/App.css @@ -4,48 +4,54 @@ body { } .container { - margin-inline: 60px; + margin-inline: auto; + padding-inline: 30px; } .navbar { background: #000; height: 56px; display: grid; - grid-template-columns: 4fr 8fr; + grid-template-columns: 160px 4fr 6fr; position: relative; z-index: 1001; + margin-bottom: 20px; } .navbar h2 { align-items: center; display: flex; - color: rgba(255, 255, 255, .15); + color: rgba(255, 255, 255, .35); + font-size: 1.2rem; } .navbar h2 svg { box-shadow: - 0 0 10px rgba(255, 216, 0, .15), - 0 0 30px rgba(255, 216, 0, .15), - 0 0 70px rgba(255, 216, 0, .15), - 0 0 100px rgba(255, 216, 0, .15), - 0 0 150px rgba(255, 216, 0, .15); + 0 0 10px rgba(255, 216, 0, .35), + 0 0 30px rgba(255, 216, 0, .35), + 0 0 70px rgba(255, 216, 0, .35), + 0 0 100px rgba(255, 216, 0, .35), + 0 0 150px rgba(255, 216, 0, .35); } .navbar .links { display: flex; - justify-content: flex-end; align-items: center; - color: rgba(255, 255, 255, .15); + color: rgba(255, 255, 255, .35); +} + +.navbar .links:last-child { + justify-content: flex-end; } .navbar .links svg { - color: rgba(255,255,255,.15); + color: rgba(255,255,255,.35); transition: all .1s ease-in-out; } .navbar .links svg:hover, .navbar .links svg:focus { - color: rgba(255, 255, 255, .5); + color: rgba(255, 255, 255, .65); } .navbar img { @@ -56,7 +62,6 @@ body { } .navbar .links a { - color: #fff; text-decoration: none; margin: 0 10px; } @@ -102,7 +107,7 @@ body { 0 0 70px rgba(255, 216, 0, .15), 0 0 100px rgba(255, 216, 0, .15), 0 0 150px rgba(255, 216, 0, .15); - transition: all .1s ease; + transition: all .1s ease-in-out; cursor: pointer; } @@ -129,11 +134,29 @@ body { background-position: var(--y) var(--x); } -@media only screen and (max-width: 1200px) { - .navbar { - margin-inline: 20px; - } +.content.mini { + min-height: 30vh; + position: relative; +} +.content.mini::after { + position: absolute; +} + +.content.mini .content__layer__text h1 { + font-size: 4rem; +} + +.content.mini .content__layer__one { + bottom: 30vh; + position: absolute; +} + +.papers__list p:last-child { + margin-bottom: 40px; +} + +@media only screen and (max-width: 1200px) { .content .content__layer__text h1 { font-size: 4rem; } diff --git a/src/App.js b/src/App.js index 309b519..f9c9cd8 100644 --- a/src/App.js +++ b/src/App.js @@ -1,65 +1,83 @@ -import { useEffect } from 'react'; -import { Helmet, HelmetProvider } from 'react-helmet-async' +import { useState } from 'react'; +import { Link, Route, Routes } from 'react-router-dom'; +import { HelmetProvider } from 'react-helmet-async' + +import { QueryClient, QueryClientProvider } from 'react-query' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core' import { fab } from '@fortawesome/free-brands-svg-icons' -import { faCoins } from '@fortawesome/free-solid-svg-icons' +import { faCoins, faMoon, faSun } from '@fortawesome/free-solid-svg-icons' -import useMousePosition from './hooks/useMousePosition'; +import Home from './home/Home'; +import Papers from './papers/Papers'; +import Paper from './papers/Paper'; + +import Meta from './seo/Meta'; import coin from './static/coin.svg'; import './App.css'; +const queryClient = new QueryClient() + library.add(fab, faCoins) function App() { - const [ref, mousePosition] = useMousePosition(); + const [darkMode, setDarkMode] = useState(true); - useEffect(() => { - document.documentElement.style.setProperty('--x', `${mousePosition.left}px`); - document.documentElement.style.setProperty('--y', `${mousePosition.top}px`); - }, [mousePosition]); + const toggleDarkMode = () => { + // Change the background of the html element + document.documentElement.classList.toggle('light'); + document.documentElement.classList.toggle('light-bg'); + + // Add the class to the body element + document.body.classList.toggle('light'); + document.body.classList.toggle('light-bg'); + + setDarkMode(!darkMode); + } return ( - - cosanostra - - + - - - - + +
+
+ +

+ coin + cosanostra +

+ -
-
-

- coin - cosanostra -

- -
+
+ papers +
-
-
-
-

a collective building value-driven on-chain primitives.

+
+ + + + + + + + + +
-
-
+ + + } /> + } /> + } /> + + ); } diff --git a/src/home/Home.js b/src/home/Home.js new file mode 100644 index 0000000..5f80d61 --- /dev/null +++ b/src/home/Home.js @@ -0,0 +1,25 @@ +import { useEffect } from 'react'; + +import useMousePosition from '../hooks/useMousePosition'; + +const Home = () => { + const [ref, mousePosition] = useMousePosition(); + + useEffect(() => { + document.documentElement.style.setProperty('--x', `${mousePosition.left}%`); + document.documentElement.style.setProperty('--y', `${mousePosition.top}%`); + }, [mousePosition]); + + return ( +
+
+
+

a collective building value-driven on-chain primitives.

+
+
+
+
+ ); +} + +export default Home; \ No newline at end of file diff --git a/src/hooks/papers.js b/src/hooks/papers.js new file mode 100644 index 0000000..a12a491 --- /dev/null +++ b/src/hooks/papers.js @@ -0,0 +1,72 @@ +const req = require.context("../../papers", true, /\.md$/); + +const processContents = (files, contents) => { + return files.map((file, index) => { + // Get the attributes from the markdown file + const parsedContents = contents[index].split("---"); + const attributes = parsedContents[0].split("\n"); + const attributesObject = {}; + attributes.forEach((attribute) => { + const [key, value] = attribute.split(":"); + + if (key && value) { + attributesObject[key.trim()] = value.trim(); + } + }); + + // Get the content from the markdown file + const content = parsedContents[1]; + + return { + filename: file.filename, + attributes: attributesObject, + content, + }; + }); +}; + +const fetchPapers = async () => { + // Get all markdown papers in /papers + const files = req.keys().map((filename) => { + const file = req(filename); + filename = filename + .replace("./", "") + .replace(".md", ""); + + return { + filename, + file, + }; + }); + + // Get the content of all the files + const papers = Promise.all( + files.map(async (file) => { + return fetch(file.file).then((response) => response.text()); + }) + ).then((contents) => processContents(files, contents)); + + return papers; +} + +const fetchPaper = async (query) => { + // Import the specific paper + + const req = require.context("../../papers", true, /\.md$/); + + // Get the filename from the query + const filename = query.queryKey[1]; + + // Get the file + const file = req(`./${filename}`); + + // Get the content of the file + const paper = await fetch(file).then((response) => response.text()); + + return processContents([file], [paper])[0]; +} + +module.exports = { + fetchPapers, + fetchPaper +} \ No newline at end of file diff --git a/src/hooks/useMousePosition.js b/src/hooks/useMousePosition.js index 929b934..865b3e6 100644 --- a/src/hooks/useMousePosition.js +++ b/src/hooks/useMousePosition.js @@ -6,14 +6,15 @@ const useMousePosition = () => { top: 0, }); - const handleMouseMove = useCallback( - (e) => - setMousePosition({ - left: e.pageX, - top: e.pageY, - }), - [] - ); + const handleMouseMove = useCallback((e) => { + const left = e.pageX / window.innerWidth * 100; + const top = e.pageY / window.innerHeight * 100; + + setMousePosition({ + left, + top + }) + }, []); const ref = useRef(); diff --git a/src/hooks/useScroll.js b/src/hooks/useScroll.js new file mode 100644 index 0000000..7a026cf --- /dev/null +++ b/src/hooks/useScroll.js @@ -0,0 +1,19 @@ +import { useEffect, useState } from 'react'; + +const useScroll = () => { + const [scroll, setScroll] = useState(0); + const handleScroll = () => { + setScroll(window.scrollY); + }; + + useEffect(() => { + window.addEventListener('scroll', handleScroll); + return () => { + window.removeEventListener('scroll', handleScroll); + }; + }, []); + + return scroll; +} + +export default useScroll; \ No newline at end of file diff --git a/src/index.css b/src/index.css index 25c7c87..cf13474 100644 --- a/src/index.css +++ b/src/index.css @@ -8,7 +8,79 @@ font-family: 'Telugu MN', serif; } +html, body { + margin: 0; +} + +h1, h2, h3, h4, h5 { + color: rgba(255, 255, 255, 0.85) +} + +p { + color: rgba(255, 255, 255, 0.65) +} + +ul, ol, li { + color: rgba(255, 255, 255, 0.55) +} + a { text-decoration: none; - color: rgba(255 255 255 0.35) + color: rgba(255, 255, 255, 0.35); + transition: all .1s ease-in-out; +} + +a:hover, +a:focus { + color: rgba(255, 255, 255, 0.65); +} + +.light { + transition: all .1s ease-in-out; +} + +.light-bg { + background: #fff; +} + +.light body { + background: #fff; +} + +.light h1, +.light h2, +.light h3, +.light h4, +.light h5 { + color: rgba(0, 0, 0, 0.85) +} + +.light p { + color: rgba(0, 0, 0, 0.65) +} + +.light ul, .light ol, .light li { + color: rgba(0, 0, 0, 0.55) +} + +.light a { + color: rgba(0, 0, 0, 0.35); +} + +.light a:hover, +.light a:focus { + color: rgba(0, 0, 0, 0.65); +} + +.light .navbar { + background: #fff; +} + +.light .navbar .links svg { + color:rgba(0, 0, 0, 0.35); +} + +.light .navbar .links svg:hover, +.light .navbar .links svg:focus { + color:rgba(0, 0, 0, 0.65); } \ No newline at end of file diff --git a/src/index.js b/src/index.js index b2f8d15..7f03527 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,15 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; +import { BrowserRouter as Router } from 'react-router-dom'; + import './index.css'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( - + + + ); \ No newline at end of file diff --git a/src/papers/Paper.css b/src/papers/Paper.css new file mode 100644 index 0000000..c335285 --- /dev/null +++ b/src/papers/Paper.css @@ -0,0 +1,29 @@ +.paper { + min-height: 100vh; + margin-bottom: 80px; +} + +.paper .container { + max-width: 650px; +} + +.paper .markdown p img { + position: relative; + width: 100%; + height: auto; +} + +.paper .attributes { + margin-bottom: 40px; +} + +.paper-progress { + position: fixed; + top: 0; + left: 0; + width: 2px; + height: 2px; + background: #FFD800; + z-index: 100; + transition: all 0.1s ease; +} \ No newline at end of file diff --git a/src/papers/Paper.js b/src/papers/Paper.js new file mode 100644 index 0000000..11547a4 --- /dev/null +++ b/src/papers/Paper.js @@ -0,0 +1,63 @@ +import Markdown from 'markdown-to-jsx'; + +import { useEffect } from 'react'; +import { useQuery } from 'react-query'; +import { useParams } from 'react-router-dom'; + +import { fetchPaper } from "../hooks/papers"; + +import Meta from '../seo/Meta'; + +import useMousePosition from '../hooks/useMousePosition'; + +import "./Paper.css" + +const Paper = () => { + const { slug } = useParams(); + + const query = useQuery(["paper", `${slug}.md`], fetchPaper); + + const [ref, mousePosition] = useMousePosition(); + + useEffect(() => { + document.documentElement.style.setProperty('--x', `${mousePosition.left}%`); + document.documentElement.style.setProperty('--y', `${mousePosition.top}%`); + }, [mousePosition]); + + // Render paper + return ( + <> + + +
+
+
+
+

{query?.data?.attributes?.title}

+
+
+
+ +

{query?.data?.attributes?.date} | {query?.data?.attributes?.author}

+ + {query?.data?.content && + {query.data.content} + } +
+
+ + ); +} + +export default Paper; \ No newline at end of file diff --git a/src/papers/Papers.js b/src/papers/Papers.js new file mode 100644 index 0000000..4768045 --- /dev/null +++ b/src/papers/Papers.js @@ -0,0 +1,54 @@ +import { useEffect } from 'react'; +import { useQuery } from 'react-query'; +import { Link } from 'react-router-dom'; + +import { fetchPapers } from "../hooks/papers"; + +import Meta from '../seo/Meta'; + +import useMousePosition from '../hooks/useMousePosition'; + +const Papers = () => { + const title = "papers | cosanostra"; + const description = "research & development of primitive & protocol for on-chain organizations, defi, and web3. explore value-driven on-chain primitives by crypto developers & value-creating products by web3 operators."; + + const query = useQuery("papers", fetchPapers); + + const [ref, mousePosition] = useMousePosition(); + + useEffect(() => { + document.documentElement.style.setProperty('--x', `${mousePosition.left}%`); + document.documentElement.style.setProperty('--y', `${mousePosition.top}%`); + }, [mousePosition]); + + return ( + <> + + +
+
+
+
+

Research papers published by the cosanostra collective.

+
+
+
+
+ +
+
+ {query?.data && query?.data.map((paper, index) => ( + +

{paper.attributes.title}

+

{paper.attributes.description}

+

{paper.attributes.date} | {paper.attributes.author}

+ + ))} +
+
+
+ + ); +} + +export default Papers; \ No newline at end of file diff --git a/src/seo/Meta.js b/src/seo/Meta.js new file mode 100644 index 0000000..5d2389f --- /dev/null +++ b/src/seo/Meta.js @@ -0,0 +1,17 @@ +import { Helmet } from 'react-helmet-async'; + +const Meta = ({ title, description }) => { + return ( + + {title} + + + + + + + + ) +} + +export default Meta;