Create subscription setup page for Monero subscriptions

This commit is contained in:
silverpill 2022-08-27 00:12:41 +00:00
parent 9a8c9c2a86
commit 2e1820c7d1
5 changed files with 206 additions and 4 deletions

View file

@ -0,0 +1,39 @@
import { BigNumber } from "@ethersproject/bignumber"
import { BACKEND_URL } from "@/constants"
import { http } from "./common"
import {
formatAmount,
getPricePerMonth as _getPricePerMonth,
getPricePerSec as _getPricePerSec,
} from "./subscriptions"
import { Profile, User } from "./users"
export function getPricePerSec(pricePerMonth: number): number {
return _getPricePerSec(pricePerMonth, 12).toNumber()
}
export function getPricePerMonth(pricePerSec: number): number {
const pricePerSecInt = BigNumber.from(pricePerSec)
const pricePerMonthInt = _getPricePerMonth(pricePerSecInt)
return formatAmount(pricePerMonthInt, 12).toUnsafeFloat()
}
export async function enableMoneroSubscriptions(
authToken: string,
price: number,
payoutAddress: string,
): Promise<User> {
const url = `${BACKEND_URL}/api/v1/subscriptions/enable`
const response = await http(url, {
method: "POST",
authToken,
json: { type: "monero", price, payout_address: payoutAddress },
})
const data = await response.json()
if (response.status !== 200) {
throw new Error(data.message)
} else {
return data
}
}

View file

@ -40,6 +40,19 @@ export function getPricePerSec(
return pricePerMonthInt.div(SECONDS_IN_MONTH)
}
export function getPricePerMonth(
pricePerSec: BigNumber,
): BigNumber {
return roundBigNumber(pricePerSec.mul(SECONDS_IN_MONTH), 4)
}
export function formatAmount(
value: BigNumber,
tokenDecimals: number,
): FixedNumber {
return FixedNumber.fromValue(value, tokenDecimals)
}
export async function getSubscriptionAuthorization(
authToken: string,
pricePerSec: BigNumber,
@ -139,11 +152,11 @@ export class SubscriptionConfig {
// Convert raw token amount to FixedNumber
formatAmount(value: BigNumber): FixedNumber {
return FixedNumber.fromValue(value, this.tokenDecimals)
return formatAmount(value, this.tokenDecimals)
}
get pricePerMonthInt(): BigNumber {
return roundBigNumber(this.price.mul(SECONDS_IN_MONTH), 4)
return getPricePerMonth(this.price)
}
get pricePerMonth(): FixedNumber {

View file

@ -0,0 +1,143 @@
<template>
<div class="subscription-settings">
<div class="info" v-if="!isLoading">
<template v-if="subscriptionOption !== null">
Subscriptions are enabled
<div class="price">
{{ getPricePerMonth(subscriptionOption.price) }} XMR per month
</div>
</template>
<template v-else>
Subscriptions are not enabled
</template>
</div>
<form v-if="canEnableSubscriptions()">
<div class="price-input-group">
<label for="price">Price</label>
<input type="number" id="price" v-model="subscriptionPrice" min="0.00" step="0.01">
<span>XMR per month</span>
</div>
<input
type="text"
id="payout_address"
v-model="subscriptionPayoutAddress"
placeholder="Payout address"
>
<button
type="submit"
class="btn"
:disabled="!isFormValid()"
@click.prevent="enableSubscriptions()"
>
Enable subscriptions
</button>
</form>
<loader v-if="isLoading"></loader>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue"
import { $, $ref } from "vue/macros"
import { getSubscriptionOptions, SubscriptionOption } from "@/api/subscriptions"
import {
enableMoneroSubscriptions,
getPricePerMonth,
getPricePerSec,
} from "@/api/subscriptions-monero"
import Loader from "@/components/Loader.vue"
import { useCurrentUser } from "@/store/user"
const { ensureAuthToken, setCurrentUser } = $(useCurrentUser())
const subscriptionPrice = $ref(0.01)
const subscriptionPayoutAddress = $ref("")
let isLoading = $ref(false)
let subscriptionOption = $ref<SubscriptionOption | null>(null)
onMounted(async () => {
isLoading = true
await loadSubscriptionConfig()
isLoading = false
})
async function loadSubscriptionConfig() {
const subscriptionOptions = await getSubscriptionOptions(ensureAuthToken())
subscriptionOption = subscriptionOptions.find((item) => {
return item.type === "monero"
}) || null
}
function canEnableSubscriptions(): boolean {
return (
!isLoading &&
subscriptionOption === null
)
}
function isFormValid(): boolean {
return (
getPricePerSec(subscriptionPrice) > 0 &&
subscriptionPayoutAddress.length > 0
)
}
async function enableSubscriptions() {
isLoading = true
const user = await enableMoneroSubscriptions(
ensureAuthToken(),
getPricePerSec(subscriptionPrice),
subscriptionPayoutAddress,
)
setCurrentUser(user)
await loadSubscriptionConfig()
isLoading = false
}
</script>
<style scoped lang="scss">
@import "../styles/layout";
@import "../styles/theme";
.info {
background-color: $block-background-color;
border-radius: $block-border-radius;
display: flex;
flex-direction: column;
gap: $block-inner-padding / 2;
padding: $block-inner-padding;
.price {
font-size: 16px;
font-weight: bold;
}
}
form {
align-items: center;
display: flex;
flex-direction: column;
gap: $block-inner-padding;
}
.price-input-group {
align-items: center;
display: flex;
font-size: 16px;
gap: $input-padding;
justify-content: center;
label {
font-weight: bold;
}
input {
width: 100px;
}
}
.loader {
margin: 0 auto;
}
</style>

View file

@ -448,7 +448,6 @@ function canManageSubscriptions(): boolean {
// Only users with verified address can configure subscription
const blockchain = instance?.blockchains[0]
return (
Boolean(blockchain?.contract_address) &&
Boolean(blockchain?.features.subscriptions) &&
profile !== null &&
profile.getVerifiedEthereumAddress() !== null &&
@ -459,7 +458,6 @@ function canManageSubscriptions(): boolean {
function canSubscribe(): boolean {
const blockchain = instance?.blockchains[0]
return (
Boolean(blockchain?.contract_address) &&
Boolean(blockchain?.features.subscriptions) &&
profile !== null &&
profile.getVerifiedEthereumAddress() !== null &&

View file

@ -3,6 +3,7 @@
<template #content>
<h1>Manage subscriptions</h1>
<subscription-settings-ethereum v-if="isEthereum()"></subscription-settings-ethereum>
<subscription-settings-monero v-if="isMonero()"></subscription-settings-monero>
</template>
</sidebar-layout>
</template>
@ -12,6 +13,7 @@ import { $, $computed } from "vue/macros"
import SidebarLayout from "@/components/SidebarLayout.vue"
import SubscriptionSettingsEthereum from "@/components/SubscriptionSettingsEthereum.vue"
import SubscriptionSettingsMonero from "@/components/SubscriptionSettingsMonero.vue"
import { useInstanceInfo } from "@/store/instance"
const { instance } = $(useInstanceInfo())
@ -24,6 +26,13 @@ function isEthereum(): boolean {
}
return blockchain.chain_id.startsWith("eip155")
}
function isMonero(): boolean {
if (!blockchain) {
return false
}
return blockchain.chain_id.startsWith("monero")
}
</script>
<style scoped lang="scss">