Show "Subscribe" button on profile page if subscriptions are enabled

This commit is contained in:
silverpill 2022-07-24 14:00:32 +00:00
parent c28e812de9
commit 31f328b0ce
5 changed files with 90 additions and 44 deletions

View file

@ -7,6 +7,7 @@ import { ethereumAddressMatch, EthereumSignature } from "@/utils/ethereum"
import { floatToBigNumber, roundBigNumber } from "@/utils/numbers"
import { http } from "./common"
import { Contracts, getContract } from "./contracts"
import { User } from "./users"
const SECONDS_IN_DAY = 3600 * 24
const SECONDS_IN_MONTH = SECONDS_IN_DAY * 30
@ -57,7 +58,7 @@ export async function getSubscriptionAuthorization(
}
}
export async function configureSubscription(
export async function configureSubscriptions(
contractAddress: string,
signer: Signer,
recipientAddress: string,
@ -75,6 +76,22 @@ export async function configureSubscription(
return transaction
}
export async function onSubscriptionsEnabled(
authToken: string,
): Promise<User> {
const url = `${BACKEND_URL}/api/v1/accounts/subscriptions_enabled`
const response = await http(url, {
method: "POST",
authToken,
})
const data = await response.json()
if (response.status !== 200) {
throw new Error(data.message)
} else {
return data
}
}
export class Subscription {
recipientAddress: string;

View file

@ -27,6 +27,8 @@ export interface Profile {
followers_count: number;
following_count: number;
statuses_count: number;
subscription_page_url: string | null;
}
export function getVerifiedEthereumAddress(profile: Profile): string | null {
@ -180,7 +182,7 @@ export async function getIdentityClaim(authToken: string): Promise<string> {
export async function createIdentityProof(
authToken: string,
signature: string,
): Promise<Profile> {
): Promise<User> {
const url = `${BACKEND_URL}/api/v1/accounts/identity_proof`
const response = await http(url, {
method: "POST",

View file

@ -26,7 +26,7 @@
<div class="wallet-error" v-if="walletError">
{{ walletError }}
</div>
<div class="info" v-if="subscriptionConfigured !== null">
<div class="info" v-if="subscriptionsEnabled !== null">
<template v-if="subscription">
<div class="price">
{{ subscription.pricePerMonth }} {{ subscription.tokenSymbol }}
@ -137,6 +137,7 @@ const guest: Profile = {
followers_count: 0,
following_count: 0,
statuses_count: 0,
subscription_page_url: null,
}
const { currentUser } = $(useCurrentUser())
@ -147,7 +148,7 @@ const recipientEthereumAddress = recipient.getVerifiedEthereumAddress()
const sender = $ref<ProfileWrapper>(new ProfileWrapper(currentUser || guest))
let senderEthereumAddress = $ref<string | null>(sender.getVerifiedEthereumAddress())
let { walletAddress, walletError, getSigner } = $(useWallet())
let subscriptionConfigured = $ref<boolean | null>(null)
let subscriptionsEnabled = $ref<boolean | null>(null)
let subscription = $ref<Subscription | null>(null)
let subscriptionState = $ref<SubscriptionState | null>(null)
let tokenBalance = $ref<BigNumber | null>(null)
@ -175,7 +176,7 @@ function canConnectWallet(): boolean {
}
function reset() {
subscriptionConfigured = null
subscriptionsEnabled = null
subscription = null
subscriptionState = null
}
@ -210,9 +211,9 @@ async function checkSubscription() {
recipientEthereumAddress,
)
if (subscription !== null) {
subscriptionConfigured = true
subscriptionsEnabled = true
} else {
subscriptionConfigured = false
subscriptionsEnabled = false
isLoading = false
return
}
@ -227,7 +228,7 @@ async function checkSubscription() {
}
function canSubscribe(): boolean {
return subscriptionConfigured === true
return subscriptionsEnabled === true
}
function getPaymentAmount(): FixedNumber {

View file

@ -1,5 +1,5 @@
<template>
<h1>Configure subscription</h1>
<h1>Manage subscriptions</h1>
<div class="subscription">
<div class="connect-wallet" v-if="canConnectWallet()">
<button class="btn" @click="connectWallet()">Connect wallet</button>
@ -7,19 +7,19 @@
<div class="wallet-error" v-if="walletError">
{{ walletError }}
</div>
<div class="info" v-if="subscriptionConfigured !== null">
<div class="info" v-if="subscriptionsEnabled !== null">
<template v-if="subscription">
<span>Subscription is enabled</span>
<span>Subscriptions are enabled</span>
<div class="price">
{{ subscription.pricePerMonth }} {{ subscription.tokenSymbol }}
<span class="price-subtext">per month</span>
</div>
</template>
<template v-else>
Subscription is not configured
Subscriptions are not enabled
</template>
</div>
<form class="setup" v-if="canConfigureSubscription()">
<form class="setup" v-if="canEnableSubscriptions()">
<div class="price">
<label for="price">Price</label>
<input type="number" id="price" v-model="subscriptionPrice" min="0.00">
@ -28,9 +28,9 @@
<button
class="btn primary"
:disabled="subscriptionPrice <= 0"
@click.prevent="onConfigureSubscription()"
@click.prevent="onEnableSubscriptions()"
>
Set up subscription
Enable subscriptions
</button>
</form>
<form class="withdraw" v-if="subscription !== null">
@ -57,14 +57,15 @@
import { onMounted, watch } from "vue"
import { $, $$, $ref } from "vue/macros"
import { getVerifiedEthereumAddress, Profile } from "@/api/users"
import { Profile, ProfileWrapper } from "@/api/users"
import {
configureSubscription,
configureSubscriptions,
getPricePerSec,
getSubscriptionAuthorization,
getSubscriptionInfo,
getSubscriptionState,
getSubscriptionToken,
onSubscriptionsEnabled,
withdrawReceived,
Subscription,
SubscriptionState,
@ -81,15 +82,16 @@ const props = defineProps<{
profile: Profile,
}>()
const { ensureAuthToken } = $(useCurrentUser())
const { ensureAuthToken, setCurrentUser } = $(useCurrentUser())
const { instance } = $(useInstanceInfo())
const { connectWallet: connectEthereumWallet, getSigner } = useWallet()
const profileEthereumAddress = getVerifiedEthereumAddress(props.profile)
const profile = new ProfileWrapper(props.profile)
const profileEthereumAddress = profile.getVerifiedEthereumAddress()
const subscriptionPrice = $ref<number>(1)
let { walletAddress, walletError } = $(useWallet())
let isLoading = $ref(false)
let subscriptionToken = $ref<SubscriptionToken | null>(null)
let subscriptionConfigured = $ref<boolean | null>(null)
let subscriptionsEnabled = $ref<boolean | null>(null)
let subscription = $ref<Subscription | null>(null)
let subscriptionState = $ref<SubscriptionState | null>(null)
let subscriberAddress = $ref<string | null>(null)
@ -113,7 +115,7 @@ function canConnectWallet(): boolean {
}
function reset() {
subscriptionConfigured = null
subscriptionsEnabled = null
subscription = null
subscriptionState = null
subscriberAddress = null
@ -149,9 +151,11 @@ async function checkSubscription() {
profileEthereumAddress,
)
if (subscription !== null) {
subscriptionConfigured = true
subscriptionsEnabled = true
// Ensure server is aware of subscription configuration
await onSubscriptionsEnabled(ensureAuthToken())
} else {
subscriptionConfigured = false
subscriptionsEnabled = false
subscriptionToken = await getSubscriptionToken(
instance.blockchain_contract_address,
signer,
@ -160,15 +164,16 @@ async function checkSubscription() {
isLoading = false
}
function canConfigureSubscription(): boolean {
function canEnableSubscriptions(): boolean {
return (
profileEthereumAddress !== null &&
subscriptionConfigured === false &&
subscriptionsEnabled === false &&
subscriptionToken !== null
)
}
async function onConfigureSubscription() {
// enableSubscriptions
async function onEnableSubscriptions() {
if (
profileEthereumAddress === null ||
!instance ||
@ -187,7 +192,7 @@ async function onConfigureSubscription() {
const signature = await getSubscriptionAuthorization(authToken, pricePerSec)
let transaction
try {
transaction = await configureSubscription(
transaction = await configureSubscriptions(
instance.blockchain_contract_address,
signer,
profileEthereumAddress,
@ -200,12 +205,15 @@ async function onConfigureSubscription() {
return
}
await transaction.wait()
subscriptionConfigured = true
subscriptionsEnabled = true
subscription = await getSubscriptionInfo(
instance.blockchain_contract_address,
signer,
profileEthereumAddress,
)
const user = await onSubscriptionsEnabled(authToken)
setCurrentUser(user)
profile.subscription_page_url = user.subscription_page_url
isLoading = false
}

View file

@ -49,20 +49,12 @@
Verify ethereum address
</button>
</li>
<li v-if="canConfigureSubscription()">
<li v-if="canManageSubscriptions()">
<router-link
title="Set up subscription"
title="Manage subscriptions"
:to="{ name: 'profile-subscription', params: { profileId: profile.id }}"
>
Set up subscription
</router-link>
</li>
<li v-if="canSubscribe()">
<router-link
title="Pay for subscription"
:to="{ name: 'profile-subscription', params: { profileId: profile.id }}"
>
Pay for subscription
Manage subscriptions
</router-link>
</li>
<li v-if="canHideReposts()">
@ -92,6 +84,26 @@
<template v-if="isFollowRequestPending()">Cancel follow request</template>
<template v-else>Unfollow</template>
</button>
<template v-if="canSubscribe()">
<router-link
v-if="isLocalUser()"
class="btn"
title="Pay for subscription"
:to="{ name: 'profile-subscription', params: { profileId: profile.id } }"
>
Subscribe
</router-link>
<a
v-else-if="profile.subscription_page_url"
class="btn"
title="Pay for subscription"
:href="profile.subscription_page_url"
target="_blank"
rel="noreferrer"
>
Subscribe
</a>
</template>
</div>
</div>
<div class="bio" v-html="profile.note"></div>
@ -205,7 +217,12 @@ import { useCurrentUser } from "@/store/user"
import { getWallet, getWalletSignature } from "@/utils/ethereum"
const route = useRoute()
const { currentUser, authToken, ensureAuthToken } = $(useCurrentUser())
const {
authToken,
currentUser,
ensureAuthToken,
setCurrentUser,
} = $(useCurrentUser())
const { instance, getActorAddress } = $(useInstanceInfo())
let profile = $ref<Profile | null>(null)
@ -403,11 +420,12 @@ async function verifyEthereumAddress(): Promise<void> {
const authToken = ensureAuthToken()
const message = await getIdentityClaim(authToken)
const signature = await getWalletSignature(signer, message)
const { identity_proofs } = await createIdentityProof(authToken, signature)
profile.identity_proofs = identity_proofs
const user = await createIdentityProof(authToken, signature)
setCurrentUser(user)
profile.identity_proofs = user.identity_proofs
}
function canConfigureSubscription(): boolean {
function canManageSubscriptions(): boolean {
// Only users with verified address can configure subscription
return (
Boolean(instance?.blockchain_contract_address) &&
@ -423,7 +441,7 @@ function canSubscribe(): boolean {
Boolean(instance?.blockchain_features?.subscription) &&
profile !== null &&
getVerifiedEthereumAddress(profile) !== null &&
isLocalUser() &&
profile.subscription_page_url !== null &&
!isCurrentUser()
)
}