Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/console/.env.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ NEXT_PUBLIC_STRIPE_CUSTOMER_PORTAL_LINK=https://billing.stripe.com/p/login/test_
# set this to skip forcing users to pick a Stripe plan
NEXT_PUBLIC_DISABLE_PLAN_GATE=false

# set this to enable Humanode identity auth as a way to pick plans
NEXT_PUBLIC_HUMANODE_AUTH_URL=https://auth.demo-storacha-2025-03-31.oauth2.humanode.io/oauth2/auth
NEXT_PUBLIC_HUMANODE_CLIENT_ID=e9756297-b2d1-4bbe-a139-a9ad1cdc43ee
NEXT_PUBLIC_HUMANODE_OAUTH_CALLBACK_URL=https://staging.up.web3.storage/oauth/humanode/callback

# point these at the marketing website and referrals service
NEXT_PUBLIC_REFERRAL_URL=http://localhost:3001/referred
NEXT_PUBLIC_REFERRALS_SERVICE_URL=http://localhost:4001
Expand Down
63 changes: 57 additions & 6 deletions packages/console/src/components/PlanGate.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,56 @@
'use client'

import { ReactNode, useState } from 'react'
import { ReactNode, useEffect, useState } from 'react'
import { useW3 } from '@storacha/ui-react'
import StripePricingTable, { StripeTrialPricingTable } from './PricingTable';
import { TopLevelLoader } from './Loader';
import { Logo } from '@/brand';
import { usePlan } from '@/hooks';
import { useRecordRefcode, useReferredBy } from '@/lib/referrals/hooks';
import { useRecordRefcode } from '@/lib/referrals/hooks';
import { useSearchParams } from 'next/navigation';
import { base64url } from 'multiformats/bases/base64'
import { authorize } from '@storacha/capabilities/access';

function HumanodeAuthLink ({className}: {className?: string}) {
const [{ accounts, client }] = useW3()
const account = accounts[0]
const [state, setState] = useState<string>()

useEffect(function () {
(async () => {
if (client) {
// Create an access/authorize request that can be used as the state of the OAuth request.
const request = await authorize.delegate({
audience: client.agent.connection.id,
issuer: client.agent.issuer,
// agent that should be granted access
with: client.agent.did(),
// capabilities requested (account access)
nb: {
iss: account.did(),
att: [{
can: '*',
}]
},
// expire this after 15 minutes
expiration: Math.floor(Date.now() / 1000) + 60 * 15
})
const archive = await request.archive()
if (archive?.ok) {
setState(base64url.encode(archive.ok))
} else {
console.warn('could not create auth delegation')
}
}
})()
}, [client, account])
return (
<a className={className || ''}
href={`${process.env.NEXT_PUBLIC_HUMANODE_AUTH_URL}?response_type=code&client_id=${process.env.NEXT_PUBLIC_HUMANODE_CLIENT_ID}&redirect_uri=${process.env.NEXT_PUBLIC_HUMANODE_OAUTH_CALLBACK_URL}&scope=openid&state=${state}`} target="_blank" rel="noopener noreferrer">
Prove my Humanity!
</a>
)
}

export function PlanGate ({ children }: { children: ReactNode }): ReactNode {
const [{ accounts }] = useW3()
Expand All @@ -19,9 +62,9 @@ export function PlanGate ({ children }: { children: ReactNode }): ReactNode {
}
if (!plan?.product) {
return (
<div className="flex flex-col justify-center items-center min-h-screen">
<div className="flex flex-col justify-center items-center min-h-screen font-epilogue ">
<div className='my-6'><Logo /></div>
<div className="max-w-screen-lg font-epilogue text-black text-center bg-white border border-hot-red rounded-2xl overflow-hidden p5 mx-4 mb-4">
<div className="max-w-screen-lg text-black text-center bg-white border border-hot-red rounded-2xl overflow-hidden p5 mx-4 mb-4">
{referredBy ? (
<>
<div className='px-6 py-6 lg:px-24'>
Expand All @@ -45,8 +88,7 @@ export function PlanGate ({ children }: { children: ReactNode }): ReactNode {
<h1 className="my-4 font-bold">Welcome, {email}!</h1>
<p className='my-4'>
To get started you&apos;ll need to sign up for a subscription. If you choose
the starter plan we won&apos;t charge your credit card, but we do need a card on file
before we will store your bits.
the starter plan we won&apos;t charge your credit card.
</p>
<p className='my-4'>
Pick a plan below and complete the Stripe checkout flow to get started!
Expand All @@ -57,6 +99,15 @@ export function PlanGate ({ children }: { children: ReactNode }): ReactNode {
)
}
</div >
<div className="3xl font-black mb-2">OR</div>
<div className="flex flex-col items-center space-y-4 bg-white border border-hot-red rounded-2xl overflow-hidden">
<div className="font-bold 3xl px-8 pt-8 pb-2">
Prove you&apos;re a human and get free storage with no credit card!
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much free storage? Forever?

</div>
<div className="bg-black w-full flex flex-col items-center p-8">
<HumanodeAuthLink className="bg-pink-300 rounded-lg py-3 w-72 text-center"/>
</div>
</div>
</div >
)
}
Expand Down
Loading