diff --git a/apps/dashboard/.env.example b/apps/dashboard/.env.example index 3f719125270..c20ff8fe6e4 100644 --- a/apps/dashboard/.env.example +++ b/apps/dashboard/.env.example @@ -108,4 +108,10 @@ STRIPE_SECRET_KEY="" # required for server wallet management NEXT_PUBLIC_THIRDWEB_VAULT_URL="" -NEXT_PUBLIC_ENGINE_CLOUD_URL="" \ No newline at end of file +NEXT_PUBLIC_ENGINE_CLOUD_URL="" + +# farcaster frame env variables +NEXT_PUBLIC_APP_URL= +NEXT_PUBLIC_FARCASTER_HEADER= +NEXT_PUBLIC_FARCASTER_PAYLOAD= +NEXT_PUBLIC_FARCASTER_SIGNATURE= \ No newline at end of file diff --git a/apps/dashboard/next.config.ts b/apps/dashboard/next.config.ts index ef23f2ed4a7..f5b13c2bcdd 100644 --- a/apps/dashboard/next.config.ts +++ b/apps/dashboard/next.config.ts @@ -29,7 +29,8 @@ const securityHeaders = [ }, { key: "X-Frame-Options", - value: "SAMEORIGIN", + // allow farcaster.xyz as a frame ancestor for the browser mini app + value: "frame-ancestors 'self' https://farcaster.xyz; default 'self'", }, { key: "Referrer-Policy", diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 0b194ad1421..75cbe7c5880 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -27,6 +27,8 @@ "@chakra-ui/theme-tools": "^2.1.2", "@emotion/react": "11.14.0", "@emotion/styled": "11.14.0", + "@farcaster/frame-core": "^0.1.8", + "@farcaster/frame-sdk": "^0.0.60", "@hookform/resolvers": "^3.9.1", "@marsidev/react-turnstile": "^1.1.0", "@radix-ui/react-accordion": "^1.2.11", diff --git a/apps/dashboard/public/.well-known/apple-app-site-association b/apps/dashboard/public/.well-known/apple-app-site-association deleted file mode 100644 index c9cac6e71c3..00000000000 --- a/apps/dashboard/public/.well-known/apple-app-site-association +++ /dev/null @@ -1,30 +0,0 @@ -{ - "applinks": { - "apps": ["XYHGSFAMHX.com.thirdweb.demo"], - "details": [ - { - "appIDs": ["XYHGSFAMHX.com.thirdweb.demo"], - "components": [ - { - "#": "no_universal_links", - "exclude": true, - "comment": "Matches any URL with a fragment that equals no_universal_links and instructs the system not to open it as a universal link." - }, - { - "/": "/mobile-wallet-protocol", - "comment": "Matches any URL with a path that starts with /mobile-wallet-protocol for coinbase wallet mobile redirects." - }, - { - "/": "/dashboard/*", - "exclude": true, - "comment": "no universal link for dashboard" - } - ] - } - ] - }, - "webcredentials": { - "apps": ["XYHGSFAMHX.com.thirdweb.demo"] - }, - "appclips": {} -} diff --git a/apps/dashboard/public/.well-known/apple-developer-merchantid-domain-association b/apps/dashboard/public/.well-known/apple-developer-merchantid-domain-association deleted file mode 100644 index 2ff95c96281..00000000000 --- a/apps/dashboard/public/.well-known/apple-developer-merchantid-domain-association +++ /dev/null @@ -1 +0,0 @@ -7B227073704964223A2239373943394538343346343131343044463144313834343232393232313734313034353044314339464446394437384337313531303944334643463542433731222C2276657273696F6E223A312C22637265617465644F6E223A313536363233343735303036312C227369676E6174757265223A22333038303036303932613836343838366637306430313037303261303830333038303032303130313331306633303064303630393630383634383031363530333034303230313035303033303830303630393261383634383836663730643031303730313030303061303830333038323033653333303832303338386130303330323031303230323038346333303431343935313964353433363330306130363038326138363438636533643034303330323330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333031653137306433313339333033353331333833303331333333323335333735613137306433323334333033353331333633303331333333323335333735613330356633313235333032333036303335353034303330633163363536333633326437333664373032643632373236663662363537323264373336393637366535663535343333343264353035323466343433313134333031323036303335353034306230633062363934663533323035333739373337343635366437333331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333035393330313330363037326138363438636533643032303130363038326138363438636533643033303130373033343230303034633231353737656465626436633762323231386636386464373039306131323138646337623062643666326332383364383436303935643934616634613534313162383334323065643831316633343037653833333331663163353463336637656233323230643662616435643465666634393238393839336537633066313361333832303231313330383230323064333030633036303335353164313330313031666630343032333030303330316630363033353531643233303431383330313638303134323366323439633434663933653465663237653663346636323836633366613262626664326534623330343530363038326230363031303530353037303130313034333933303337333033353036303832623036303130353035303733303031383632393638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635363136393633363133333330333233303832303131643036303335353164323030343832303131343330383230313130333038323031306330363039326138363438383666373633363430353031333038316665333038316333303630383262303630313035303530373032303233303831623630633831623335323635366336393631366536333635323036663665323037343638363937333230363336353732373436393636363936333631373436353230363237393230363136653739323037303631373237343739323036313733373337353664363537333230363136333633363537303734363136653633363532303666363632303734363836353230373436383635366532303631373037303663363936333631363236633635323037333734363136653634363137323634323037343635373236643733323036313665363432303633366636653634363937343639366636653733323036663636323037353733363532633230363336353732373436393636363936333631373436353230373036663663363936333739323036313665363432303633363537323734363936363639363336313734363936663665323037303732363136333734363936333635323037333734363137343635366436353665373437333265333033363036303832623036303130353035303730323031313632613638373437343730336132663266373737373737326536313730373036633635326536333666366432663633363537323734363936363639363336313734363536313735373436383666373236393734373932663330333430363033353531643166303432643330326233303239613032376130323538363233363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353631363936333631333332653633373236633330316430363033353531643065303431363034313439343537646236666435373438313836383938393736326637653537383530376537396235383234333030653036303335353164306630313031666630343034303330323037383033303066303630393261383634383836663736333634303631643034303230353030333030613036303832613836343863653364303430333032303334393030333034363032323130306265303935373166653731653165373335623535653561666163623463373266656234343566333031383532323263373235313030326236316562643666353530323231303064313862333530613564643664643665623137343630333562313165623263653837636661336536616636636264383338303839306463383263646461613633333038323032656533303832303237356130303330323031303230323038343936643266626633613938646139373330306130363038326138363438636533643034303330323330363733313162333031393036303335353034303330633132343137303730366336353230353236663666373432303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133343330333533303336333233333334333633333330356131373064333233393330333533303336333233333334333633333330356133303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346630313731313834313964373634383564353161356532353831303737366538383061326566646537626165346465303864666334623933653133333536643536363562333561653232643039373736306432323465376262613038666437363137636538386362373662623636373062656338653832393834666635343435613338316637333038316634333034363036303832623036303130353035303730313031303433613330333833303336303630383262303630313035303530373330303138363261363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363537323666366637343633363136373333333031643036303335353164306530343136303431343233663234396334346639336534656632376536633466363238366333666132626266643265346233303066303630333535316431333031303166663034303533303033303130316666333031663036303335353164323330343138333031363830313462626230646561313538333338383961613438613939646562656264656261666461636232346162333033373036303335353164316630343330333032653330326361303261613032383836323636383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635373236663666373436333631363733333265363337323663333030653036303335353164306630313031666630343034303330323031303633303130303630613261383634383836663736333634303630323065303430323035303033303061303630383261383634386365336430343033303230333637303033303634303233303361636637323833353131363939623138366662333563333536636136326266663431376564643930663735346461323865626566313963383135653432623738396638393866373962353939663938643534313064386639646539633266653032333033323264643534343231623061333035373736633564663333383362393036376664313737633263323136643936346663363732363938323132366635346638376137643162393963623962303938393231363130363939306630393932316430303030333138323031386233303832303138373032303130313330383138363330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533303230383463333034313439353139643534333633303064303630393630383634383031363530333034303230313035303061303831393533303138303630393261383634383836663730643031303930333331306230363039326138363438383666373064303130373031333031633036303932613836343838366637306430313039303533313066313730643331333933303338333133393331333733313332333333303561333032613036303932613836343838366637306430313039333433313164333031623330306430363039363038363438303136353033303430323031303530306131306130363038326138363438636533643034303330323330326630363039326138363438383666373064303130393034333132323034323062303731303365313430613462386231376262613230316130336163643036396234653431366232613263383066383661383338313435633239373566633131333030613036303832613836343863653364303430333032303434363330343430323230343639306264636637626461663833636466343934396534633035313039656463663334373665303564373261313264376335666538633033303033343464663032323032363764353863393365626233353031333836363062353730373938613064643731313734316262353864626436613138363633353038353431656565393035303030303030303030303030227D \ No newline at end of file diff --git a/apps/dashboard/public/.well-known/assetlinks.json b/apps/dashboard/public/.well-known/assetlinks.json deleted file mode 100644 index 46c70f80a5b..00000000000 --- a/apps/dashboard/public/.well-known/assetlinks.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "relation": [ - "delegate_permission/common.handle_all_urls", - "delegate_permission/common.get_login_creds" - ], - "target": { - "namespace": "android_app", - "package_name": "com.thirdweb.demo", - "sha256_cert_fingerprints": [ - "40:EB:0D:96:57:F3:D8:1F:BA:87:B8:E4:26:E0:3A:DB:C8:35:96:A8:A2:B2:55:F0:B1:64:F1:39:F8:6F:7E:EB" - ] - } - } -] diff --git a/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.png b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.png new file mode 100644 index 00000000000..f8e5744a0b4 Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.png differ diff --git a/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.svg b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.svg new file mode 100644 index 00000000000..8bf89db8383 --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/apps/dashboard/public/assets/nebula/frame/farcaster-logo.svg b/apps/dashboard/public/assets/nebula/frame/farcaster-logo.svg new file mode 100644 index 00000000000..062943dd91c --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/farcaster-logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/dashboard/public/assets/nebula/frame/frame.png b/apps/dashboard/public/assets/nebula/frame/frame.png new file mode 100644 index 00000000000..39ef1e6338a Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/frame.png differ diff --git a/apps/dashboard/public/assets/nebula/frame/hero.svg b/apps/dashboard/public/assets/nebula/frame/hero.svg new file mode 100644 index 00000000000..8873deaae87 --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/hero.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + AskNebula + Your Web3 AI Assistant + \ No newline at end of file diff --git a/apps/dashboard/public/assets/nebula/frame/icon.png b/apps/dashboard/public/assets/nebula/frame/icon.png new file mode 100644 index 00000000000..f8e5744a0b4 Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/icon.png differ diff --git a/apps/dashboard/public/assets/nebula/frame/icon.svg b/apps/dashboard/public/assets/nebula/frame/icon.svg new file mode 100644 index 00000000000..84228c6dd3f --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/dashboard/public/assets/nebula/frame/og.svg b/apps/dashboard/public/assets/nebula/frame/og.svg new file mode 100644 index 00000000000..cd00953b3ae --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/og.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + AskNebula + Web3 AI Assistant + + + Ask questions about your web3 activity + Get AI-powered insights about your wallet + Explore blockchain data through natural language + \ No newline at end of file diff --git a/apps/dashboard/public/assets/nebula/frame/screenshot.svg b/apps/dashboard/public/assets/nebula/frame/screenshot.svg new file mode 100644 index 00000000000..9e6eb1de640 --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/screenshot.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + AskNebula + by cromewar.eth + + + + × + + + + + + + Vasiliy Kirochka + 0x1ca8...01d1 + + + + + + + + + + AskNebula Chat + + + + Session + active + + + + Wallet + connected + + + + + Welcome to AskNebula chat! Ask me + anything about your web3 activity. + less than a minute ago + + + + What is my balance? + + + What was my last transaction? + + + What was my last minted NFT? + + + + Ask me anything? + + + \ No newline at end of file diff --git a/apps/dashboard/public/assets/nebula/frame/splash.png b/apps/dashboard/public/assets/nebula/frame/splash.png new file mode 100644 index 00000000000..a1ea30a62c7 Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/splash.png differ diff --git a/apps/dashboard/public/assets/nebula/frame/splash.svg b/apps/dashboard/public/assets/nebula/frame/splash.svg new file mode 100644 index 00000000000..8bb9456be77 --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/splash.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/dashboard/public/assets/nebula/frame/thirdweb-logo.png b/apps/dashboard/public/assets/nebula/frame/thirdweb-logo.png new file mode 100644 index 00000000000..ec919ab48eb --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/thirdweb-logo.png @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/dashboard/public/assets/nebula/frame/user-logo.svg b/apps/dashboard/public/assets/nebula/frame/user-logo.svg new file mode 100644 index 00000000000..44dc35cbd08 --- /dev/null +++ b/apps/dashboard/public/assets/nebula/frame/user-logo.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/apps/dashboard/src/app/.well-known/apple-app-site-association.json/route.ts b/apps/dashboard/src/app/.well-known/apple-app-site-association.json/route.ts new file mode 100644 index 00000000000..ceefb7da147 --- /dev/null +++ b/apps/dashboard/src/app/.well-known/apple-app-site-association.json/route.ts @@ -0,0 +1,36 @@ +import { NextResponse } from "next/server"; + +export async function GET() { + return NextResponse.json({ + applinks: { + apps: ["XYHGSFAMHX.com.thirdweb.demo"], + details: [ + { + appIDs: ["XYHGSFAMHX.com.thirdweb.demo"], + components: [ + { + "#": "no_universal_links", + exclude: true, + comment: + "Matches any URL with a fragment that equals no_universal_links and instructs the system not to open it as a universal link.", + }, + { + "/": "/mobile-wallet-protocol", + comment: + "Matches any URL with a path that starts with /mobile-wallet-protocol for coinbase wallet mobile redirects.", + }, + { + "/": "/dashboard/*", + exclude: true, + comment: "no universal link for dashboard", + }, + ], + }, + ], + }, + webcredentials: { + apps: ["XYHGSFAMHX.com.thirdweb.demo"], + }, + appclips: {}, + }); +} diff --git a/apps/dashboard/src/app/.well-known/apple-developer-merchantid-domain-association/route.ts b/apps/dashboard/src/app/.well-known/apple-developer-merchantid-domain-association/route.ts new file mode 100644 index 00000000000..7d84734a856 --- /dev/null +++ b/apps/dashboard/src/app/.well-known/apple-developer-merchantid-domain-association/route.ts @@ -0,0 +1,3 @@ +export async function GET() { + return "7B227073704964223A2239373943394538343346343131343044463144313834343232393232313734313034353044314339464446394437384337313531303944334643463542433731222C2276657273696F6E223A312C22637265617465644F6E223A313536363233343735303036312C227369676E6174757265223A22333038303036303932613836343838366637306430313037303261303830333038303032303130313331306633303064303630393630383634383031363530333034303230313035303033303830303630393261383634383836663730643031303730313030303061303830333038323033653333303832303338386130303330323031303230323038346333303431343935313964353433363330306130363038326138363438636533643034303330323330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333031653137306433313339333033353331333833303331333333323335333735613137306433323334333033353331333633303331333333323335333735613330356633313235333032333036303335353034303330633163363536333633326437333664373032643632373236663662363537323264373336393637366535663535343333343264353035323466343433313134333031323036303335353034306230633062363934663533323035333739373337343635366437333331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333035393330313330363037326138363438636533643032303130363038326138363438636533643033303130373033343230303034633231353737656465626436633762323231386636386464373039306131323138646337623062643666326332383364383436303935643934616634613534313162383334323065643831316633343037653833333331663163353463336637656233323230643662616435643465666634393238393839336537633066313361333832303231313330383230323064333030633036303335353164313330313031666630343032333030303330316630363033353531643233303431383330313638303134323366323439633434663933653465663237653663346636323836633366613262626664326534623330343530363038326230363031303530353037303130313034333933303337333033353036303832623036303130353035303733303031383632393638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635363136393633363133333330333233303832303131643036303335353164323030343832303131343330383230313130333038323031306330363039326138363438383666373633363430353031333038316665333038316333303630383262303630313035303530373032303233303831623630633831623335323635366336393631366536333635323036663665323037343638363937333230363336353732373436393636363936333631373436353230363237393230363136653739323037303631373237343739323036313733373337353664363537333230363136333633363537303734363136653633363532303666363632303734363836353230373436383635366532303631373037303663363936333631363236633635323037333734363136653634363137323634323037343635373236643733323036313665363432303633366636653634363937343639366636653733323036663636323037353733363532633230363336353732373436393636363936333631373436353230373036663663363936333739323036313665363432303633363537323734363936363639363336313734363936663665323037303732363136333734363936333635323037333734363137343635366436353665373437333265333033363036303832623036303130353035303730323031313632613638373437343730336132663266373737373737326536313730373036633635326536333666366432663633363537323734363936363639363336313734363536313735373436383666373236393734373932663330333430363033353531643166303432643330326233303239613032376130323538363233363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353631363936333631333332653633373236633330316430363033353531643065303431363034313439343537646236666435373438313836383938393736326637653537383530376537396235383234333030653036303335353164306630313031666630343034303330323037383033303066303630393261383634383836663736333634303631643034303230353030333030613036303832613836343863653364303430333032303334393030333034363032323130306265303935373166653731653165373335623535653561666163623463373266656234343566333031383532323263373235313030326236316562643666353530323231303064313862333530613564643664643665623137343630333562313165623263653837636661336536616636636264383338303839306463383263646461613633333038323032656533303832303237356130303330323031303230323038343936643266626633613938646139373330306130363038326138363438636533643034303330323330363733313162333031393036303335353034303330633132343137303730366336353230353236663666373432303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133343330333533303336333233333334333633333330356131373064333233393330333533303336333233333334333633333330356133303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346630313731313834313964373634383564353161356532353831303737366538383061326566646537626165346465303864666334623933653133333536643536363562333561653232643039373736306432323465376262613038666437363137636538386362373662623636373062656338653832393834666635343435613338316637333038316634333034363036303832623036303130353035303730313031303433613330333833303336303630383262303630313035303530373330303138363261363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363537323666366637343633363136373333333031643036303335353164306530343136303431343233663234396334346639336534656632376536633466363238366333666132626266643265346233303066303630333535316431333031303166663034303533303033303130316666333031663036303335353164323330343138333031363830313462626230646561313538333338383961613438613939646562656264656261666461636232346162333033373036303335353164316630343330333032653330326361303261613032383836323636383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635373236663666373436333631363733333265363337323663333030653036303335353164306630313031666630343034303330323031303633303130303630613261383634383836663736333634303630323065303430323035303033303061303630383261383634386365336430343033303230333637303033303634303233303361636637323833353131363939623138366662333563333536636136326266663431376564643930663735346461323865626566313963383135653432623738396638393866373962353939663938643534313064386639646539633266653032333033323264643534343231623061333035373736633564663333383362393036376664313737633263323136643936346663363732363938323132366635346638376137643162393963623962303938393231363130363939306630393932316430303030333138323031386233303832303138373032303130313330383138363330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533303230383463333034313439353139643534333633303064303630393630383634383031363530333034303230313035303061303831393533303138303630393261383634383836663730643031303930333331306230363039326138363438383666373064303130373031333031633036303932613836343838366637306430313039303533313066313730643331333933303338333133393331333733313332333333303561333032613036303932613836343838366637306430313039333433313164333031623330306430363039363038363438303136353033303430323031303530306131306130363038326138363438636533643034303330323330326630363039326138363438383666373064303130393034333132323034323062303731303365313430613462386231376262613230316130336163643036396234653431366232613263383066383661383338313435633239373566633131333030613036303832613836343863653364303430333032303434363330343430323230343639306264636637626461663833636466343934396534633035313039656463663334373665303564373261313264376335666538633033303033343464663032323032363764353863393365626233353031333836363062353730373938613064643731313734316262353864626436613138363633353038353431656565393035303030303030303030303030227D"; +} diff --git a/apps/dashboard/src/app/.well-known/assetlinks.json/route.ts b/apps/dashboard/src/app/.well-known/assetlinks.json/route.ts new file mode 100644 index 00000000000..47374d23c2a --- /dev/null +++ b/apps/dashboard/src/app/.well-known/assetlinks.json/route.ts @@ -0,0 +1,19 @@ +import { NextResponse } from "next/server"; + +export async function GET() { + return NextResponse.json([ + { + relation: [ + "delegate_permission/common.handle_all_urls", + "delegate_permission/common.get_login_creds", + ], + target: { + namespace: "android_app", + package_name: "com.thirdweb.demo", + sha256_cert_fingerprints: [ + "40:EB:0D:96:57:F3:D8:1F:BA:87:B8:E4:26:E0:3A:DB:C8:35:96:A8:A2:B2:55:F0:B1:64:F1:39:F8:6F:7E:EB", + ], + }, + }, + ]); +} diff --git a/apps/dashboard/src/app/.well-known/farcaster.json/route.ts b/apps/dashboard/src/app/.well-known/farcaster.json/route.ts new file mode 100644 index 00000000000..92a218023b4 --- /dev/null +++ b/apps/dashboard/src/app/.well-known/farcaster.json/route.ts @@ -0,0 +1,47 @@ +import { NextResponse } from "next/server"; + +export async function GET() { + try { + const appUrl = + process.env.NEXT_PUBLIC_APP_URL || "http://nebula---localhost:3000"; + const manifest = { + accountAssociation: { + header: process.env.NEXT_PUBLIC_FARCASTER_HEADER, + payload: process.env.NEXT_PUBLIC_FARCASTER_PAYLOAD, + signature: process.env.NEXT_PUBLIC_FARCASTER_SIGNATURE, + }, + frame: { + version: "1", + name: "Nebula", + iconUrl: `${appUrl}/assets/nebula/frame/ask-nebula-pfp.png`, + imageUrl: `${appUrl}/assets/nebula/frame/frame.png`, + homeUrl: appUrl, + splashImageUrl: `${appUrl}/assets/nebula/frame/ask-nebula-pfp.png`, + splashBackgroundColor: "#171B20", + subtitle: "Web3 AI Assistant", + description: + "Ask questions about your web3 activity, get AI-powered insights about your wallet, and explore blockchain data through natural language", + primaryCategory: "utility", + tags: ["ai", "web3", "blockchain", "insights", "wallet"], + tagline: "Your AI guide to web3", + ogTitle: "Nebula - Web3 AI Assistant", + ogDescription: + "Interact with your wallet data through natural language queries powered by Thirdweb Nebula AI", + heroImageUrl: `${appUrl}/assets/nebula/frame/screenshot.svg`, + ogImageUrl: `${appUrl}/assets/nebula/frame/og.svg`, + screenshotUrls: [ + `${appUrl}/assets/nebula/frame/screenshot.svg`, + `${appUrl}/assets/nebula/frame/frame.png`, + `${appUrl}/assets/nebula/frame/og.svg`, + ], + }, + }; + return NextResponse.json(manifest); + } catch (error) { + console.error("Error generating manifest:", error); + return NextResponse.json( + { error: (error as Error).message }, + { status: 500 }, + ); + } +} diff --git a/apps/dashboard/src/app/nebula-app/(app)/_farcaster/miniapp-provider.tsx b/apps/dashboard/src/app/nebula-app/(app)/_farcaster/miniapp-provider.tsx new file mode 100644 index 00000000000..00424ee3ba2 --- /dev/null +++ b/apps/dashboard/src/app/nebula-app/(app)/_farcaster/miniapp-provider.tsx @@ -0,0 +1,125 @@ +"use client"; + +import type { AddMiniAppResult } from "@farcaster/frame-core/dist/actions/AddMiniApp"; +import type { FrameContext } from "@farcaster/frame-core/dist/context"; +import { sdk } from "@farcaster/frame-sdk"; +import { useQuery } from "@tanstack/react-query"; +import { type ReactNode, createContext, useCallback, useState } from "react"; +import { base } from "thirdweb/chains"; +import { useConnect } from "thirdweb/react"; +import { EIP1193 } from "thirdweb/wallets"; +import { nebulaAppThirdwebClient } from "../utils/nebulaThirdwebClient"; + +interface MiniAppContextType { + isMiniAppReady: boolean; + isInMiniApp: boolean; + context: FrameContext | null; + setMiniAppReady: () => void; + addMiniApp: () => Promise; +} + +// eslint-disable-next-line no-restricted-syntax +const MiniAppContext = createContext(undefined); + +export function MiniAppProvider({ + addMiniAppOnLoad, + children, +}: { + addMiniAppOnLoad?: boolean; + children: ReactNode; +}) { + const [context, setContext] = useState(null); + const [isMiniAppReady, setIsMiniAppReady] = useState(false); + const [isInMiniApp, setisInMiniApp] = useState(false); + const [, setError] = useState(null); + const { connect } = useConnect(); + + const connectWallet = useCallback(async () => { + connect(async () => { + const wallet = EIP1193.fromProvider({ provider: sdk.wallet.ethProvider }); + await wallet.connect({ client: nebulaAppThirdwebClient, chain: base }); + return wallet; + }); + }, [connect]); + + const setMiniAppReady = useCallback(async () => { + try { + const isInMiniApp = await sdk.isInMiniApp(); + setisInMiniApp(isInMiniApp); + if (!isInMiniApp) return; + const context = await sdk.context; + if (context) { + setContext(context as FrameContext); + } else { + setError("Failed to load Farcaster context"); + } + await sdk.actions.ready(); + if (sdk.wallet) { + await connectWallet(); + } + } catch (err) { + setError(err instanceof Error ? err.message : "Failed to initialize SDK"); + console.error("SDK initialization error:", err); + } finally { + setIsMiniAppReady(true); + } + }, [connectWallet]); + + useQuery({ + queryKey: ["miniapp-ready"], + queryFn: async () => { + try { + await setMiniAppReady(); + return true; + } catch (err) { + setError( + err instanceof Error ? err.message : "Failed to initialize SDK", + ); + console.error("SDK initialization error:", err); + return false; + } + }, + }); + + const handleAddMiniApp = useCallback(async () => { + try { + if (!isInMiniApp) return null; + const result = await sdk.actions.addFrame(); + if (result) { + return result; + } + return null; + } catch (error) { + console.error("[error] adding frame", error); + return null; + } + }, [isInMiniApp]); + + useQuery({ + queryKey: ["miniapp-add"], + queryFn: async () => { + try { + await handleAddMiniApp(); + return true; + } catch (error) { + console.error("[error] adding frame", error); + return false; + } + }, + enabled: isMiniAppReady && !context?.client?.added && addMiniAppOnLoad, + }); + + return ( + + {children} + + ); +} diff --git a/apps/dashboard/src/app/nebula-app/layout.tsx b/apps/dashboard/src/app/nebula-app/layout.tsx index 927bbc8a5eb..437ae41950a 100644 --- a/apps/dashboard/src/app/nebula-app/layout.tsx +++ b/apps/dashboard/src/app/nebula-app/layout.tsx @@ -1,4 +1,4 @@ -import type { Metadata } from "next"; +// import type { Metadata } from "next"; import "../../global.css"; import "./nebula-global.css"; import { DashboardRouterTopProgressBar } from "@/lib/DashboardRouter"; @@ -15,14 +15,34 @@ const title = const description = "The most powerful AI for interacting with the blockchain, with real-time access to EVM chains and their data"; -export const metadata: Metadata = { - title, - description, - openGraph: { +export async function generateMetadata() { + const appUrl = + process.env.NEXT_PUBLIC_APP_URL || "http://nebula---localhost:3000"; + return { title, description, - }, -}; + openGraph: { + title, + description, + }, + other: { + "fc:frame": JSON.stringify({ + version: "next", + imageUrl: `${appUrl}/assets/nebula/frame/frame.png`, + button: { + title: "Start Chatting", + action: { + type: "launch_frame", + name: "Nebula", + url: appUrl, + splashImageUrl: `${appUrl}/assets/nebula/frame/ask-nebula-pfp.png`, + splashBackgroundColor: "#0f172a", + }, + }, + }), + }, + }; +} const fontSans = Inter({ subsets: ["latin"], diff --git a/apps/dashboard/src/app/nebula-app/providers.tsx b/apps/dashboard/src/app/nebula-app/providers.tsx index 532bb20ab06..9577c5912ab 100644 --- a/apps/dashboard/src/app/nebula-app/providers.tsx +++ b/apps/dashboard/src/app/nebula-app/providers.tsx @@ -6,6 +6,7 @@ import { ThemeProvider, useTheme } from "next-themes"; import { useMemo } from "react"; import { Toaster } from "sonner"; import { ThirdwebProvider, useActiveAccount } from "thirdweb/react"; +import { MiniAppProvider } from "./(app)/_farcaster/miniapp-provider"; import { NebulaConnectWallet } from "./(app)/components/NebulaConnectButton"; const queryClient = new QueryClient(); @@ -14,17 +15,19 @@ export function NebulaProviders(props: { children: React.ReactNode }) { return ( - - - - {props.children} - - + + + + + {props.children} + + + ); diff --git a/apps/dashboard/src/middleware.ts b/apps/dashboard/src/middleware.ts index c512b0f10ec..0a134e4a7d5 100644 --- a/apps/dashboard/src/middleware.ts +++ b/apps/dashboard/src/middleware.ts @@ -48,9 +48,14 @@ export async function middleware(request: NextRequest) { // nebula.thirdweb.com -> render page at app/nebula-app // on vercel preview, the format is nebula---thirdweb-www-git-.thirdweb-preview.com if ( - subdomain && - (subdomain === "nebula" || subdomain.startsWith("nebula---")) + (subdomain && + (subdomain === "nebula" || subdomain.startsWith("nebula---"))) || + host?.includes("ngrok") ) { + // ignore well-known paths when served under nebula + if (paths[0] === ".well-known") { + return NextResponse.next(); + } // preserve search params when redirecting to /login page if ( !nebulaAuthCookie && diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9aaff733e53..ad8827faa6c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,6 +76,12 @@ importers: '@emotion/styled': specifier: 11.14.0 version: 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0) + '@farcaster/frame-core': + specifier: ^0.1.8 + version: 0.1.10(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@farcaster/frame-sdk': + specifier: ^0.0.60 + version: 0.0.60(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.62) '@hookform/resolvers': specifier: ^3.9.1 version: 3.10.0(react-hook-form@7.55.0(react@19.1.0)) @@ -3256,6 +3262,20 @@ packages: resolution: {integrity: sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==} hasBin: true + '@farcaster/frame-core@0.1.10': + resolution: {integrity: sha512-4PG0mHrk5VmDtt/HH+vs3xDaWY/KVdZLUxlFetkD/szn1NNtHUxM43vCUE/qgulmlV53x8GPBbkwHzcA7Dmpuw==} + + '@farcaster/frame-core@0.1.8': + resolution: {integrity: sha512-Y0JATQXa/iaqH3pCp8Dby4iCQbwqw7JJaGtfzUazdr7R+zs3EDP8DYQCkqJu6iGjE9gqgecB+b+DOZpnqMTDNw==} + + '@farcaster/frame-sdk@0.0.60': + resolution: {integrity: sha512-MHQwdFT1VPe3kS0NvnORBPb/DQXr8qpdSDgIgfrdVCB8byQ5uFELlr3gQMuFYFyLFQVXgbMl75z8O6+hvorqow==} + + '@farcaster/quick-auth@0.0.5': + resolution: {integrity: sha512-Z8hWz/7c33zlmII2AJHja/Wz0C03mm2o+CEBtBylmiun1wC4FMgx1Fal699VQvBUG1lpcJ662WxuRNxKogktDw==} + peerDependencies: + typescript: 5.8.3 + '@floating-ui/core@1.7.1': resolution: {integrity: sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==} @@ -7426,6 +7446,7 @@ packages: '@walletconnect/modal@2.7.0': resolution: {integrity: sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==} + deprecated: Please follow the migration guide on https://docs.reown.com/appkit/upgrade/wcm '@walletconnect/react-native-compat@2.17.3': resolution: {integrity: sha512-lHKwXKoB0rdDH1ukxUx7o86xosWbttWIHYMZ8tgAQC1k9VH3CZZCoBcHOAAX8iBzyb0n0UP3/9zRrOcJE5nz7Q==} @@ -8572,6 +8593,9 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + comlink@4.4.2: + resolution: {integrity: sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==} + comma-separated-tokens@1.0.8: resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==} @@ -11110,6 +11134,9 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + jose@6.0.11: resolution: {integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==} @@ -12619,6 +12646,14 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + ox@0.4.4: + resolution: {integrity: sha512-oJPEeCDs9iNiPs6J0rTx+Y0KGeCGyCAA3zo94yZhm8G5WpOxrwUtn2Ie/Y8IyARSqqY/j9JTKA3Fc1xs1DvFnw==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + ox@0.6.7: resolution: {integrity: sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==} peerDependencies: @@ -19229,6 +19264,48 @@ snapshots: find-up: 5.0.0 js-yaml: 4.1.0 + '@farcaster/frame-core@0.1.10(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)': + dependencies: + '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) + ox: 0.4.4(typescript@5.8.3)(zod@3.25.62) + zod: 3.25.62 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + '@farcaster/frame-core@0.1.8(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)': + dependencies: + '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) + ox: 0.4.4(typescript@5.8.3)(zod@3.25.62) + zod: 3.25.62 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + '@farcaster/frame-sdk@0.0.60(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.62)': + dependencies: + '@farcaster/frame-core': 0.1.8(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@farcaster/quick-auth': 0.0.5(typescript@5.8.3) + comlink: 4.4.2 + eventemitter3: 5.0.1 + ox: 0.4.4(typescript@5.8.3)(zod@3.25.62) + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + - zod + + '@farcaster/quick-auth@0.0.5(typescript@5.8.3)': + dependencies: + jose: 5.10.0 + typescript: 5.8.3 + zod: 3.25.62 + '@floating-ui/core@1.7.1': dependencies: '@floating-ui/utils': 0.2.9 @@ -28012,6 +28089,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 + comlink@4.4.2: {} + comma-separated-tokens@1.0.8: {} comma-separated-tokens@2.0.3: {} @@ -31203,6 +31282,8 @@ snapshots: jose@4.15.9: {} + jose@5.10.0: {} + jose@6.0.11: {} joycon@3.1.1: {} @@ -33039,6 +33120,20 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + ox@0.4.4(typescript@5.8.3)(zod@3.25.62): + dependencies: + '@adraffy/ens-normalize': 1.11.0 + '@noble/curves': 1.8.2 + '@noble/hashes': 1.7.2 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.0.8(typescript@5.8.3)(zod@3.25.62) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - zod + ox@0.6.7(typescript@5.8.3)(zod@3.25.62): dependencies: '@adraffy/ens-normalize': 1.11.0