From 73f7a3c358d084a288e2a318ea86e45c7fcedc84 Mon Sep 17 00:00:00 2001 From: silverpill Date: Thu, 27 Jan 2022 18:08:46 +0000 Subject: [PATCH] Add items to profile menu for setting up paid subscription --- src/api/subscriptions.ts | 51 ++++++++++++++++++++ src/views/Profile.vue | 102 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 src/api/subscriptions.ts diff --git a/src/api/subscriptions.ts b/src/api/subscriptions.ts new file mode 100644 index 0000000..6d0e271 --- /dev/null +++ b/src/api/subscriptions.ts @@ -0,0 +1,51 @@ +import { Signer } from "ethers" +import { TransactionResponse } from "@ethersproject/abstract-provider" + +import { BACKEND_URL } from "@/constants" +import { Signature } from "@/utils/ethereum" +import { http } from "./common" +import { getContract } from "./contracts" + +export async function getSubscriptionAuthorization( + authToken: string, +): Promise { + const url = `${BACKEND_URL}/api/v1/accounts/authorize_subscription` + const response = await http(url, { + method: "GET", + authToken, + }) + const data = await response.json() + if (response.status !== 200) { + throw new Error(data.message) + } else { + return data + } +} + +export async function configureSubscription( + contractName: string, + contractAddress: string, + signer: Signer, + recipientAddress: string, + serverSignature: Signature, +): Promise { + const adapter = await getContract(contractName, contractAddress, signer) + const transaction = await adapter.configureSubscription( + recipientAddress, + serverSignature.v, + "0x" + serverSignature.r, + "0x" + serverSignature.s, + ) + return transaction +} + +export async function isSubscriptionConfigured( + contractName: string, + contractAddress: string, + signer: Signer, + recipientAddress: string, +): Promise { + const adapter = await getContract(contractName, contractAddress, signer) + const result = await adapter.isSubscriptionConfigured(recipientAddress) + return result +} diff --git a/src/views/Profile.vue b/src/views/Profile.vue index ee6f514..4190d0f 100644 --- a/src/views/Profile.vue +++ b/src/views/Profile.vue @@ -11,7 +11,7 @@
Follows you
@@ -111,12 +126,18 @@ import { getFollowers, getFollowing, } from "@/api/relationships" +import { + getSubscriptionAuthorization, + configureSubscription, + isSubscriptionConfigured, +} from "@/api/subscriptions" import Avatar from "@/components/Avatar.vue" import PostList from "@/components/PostList.vue" import ProfileListItem from "@/components/ProfileListItem.vue" import Sidebar from "@/components/Sidebar.vue" import { useInstanceInfo } from "@/store/instance" import { useCurrentUser } from "@/store/user" +import { getSigner } from "@/utils/ethereum" @Options({ components: { @@ -130,13 +151,16 @@ export default class ProfileView extends Vue { private store = setup(() => { const { currentUser, authToken, ensureAuthToken } = useCurrentUser() - const { getActorAddress } = useInstanceInfo() - return { currentUser, authToken, ensureAuthToken, getActorAddress } + const { instance, getActorAddress } = useInstanceInfo() + return { currentUser, authToken, ensureAuthToken, instance, getActorAddress } }) profile: Profile | null = null relationship: Relationship | null = null + walletConnected = false + subscriptionConfigured: boolean | null = null + profileMenuVisible = false tabName = "posts" @@ -250,6 +274,74 @@ export default class ProfileView extends Vue { return this.profile.username === this.profile.acct } + canConnectWallet(): boolean { + return Boolean(this.store.instance?.blockchain_contract_address) && !this.walletConnected + } + + async connectWallet() { + const signer = await getSigner() + if (!signer) { + return + } + this.walletConnected = true + this.checkSubscriptionConfigured() + } + + canConfigureSubscription(): boolean { + // If wallet is not connected, subscriptionConfigured is set to null + return this.isCurrentUser() && this.subscriptionConfigured === false + } + + private async checkSubscriptionConfigured() { + const { instance } = this.store + if ( + !this.profile || + !this.profile.wallet_address || + !instance || + !instance.blockchain_contract_name || + !instance.blockchain_contract_address + ) { + return + } + const signer = await getSigner() + if (!signer) { + return + } + this.subscriptionConfigured = await isSubscriptionConfigured( + instance.blockchain_contract_name, + instance.blockchain_contract_address, + signer, + this.profile.wallet_address, + ) + } + + async configureSubscription() { + const { currentUser, instance } = this.store + if ( + !currentUser || + !instance || + !instance.blockchain_contract_name || + !instance.blockchain_contract_address + ) { + return + } + // Subscription configuration tx can be send from any address + const signer = await getSigner() + if (!signer) { + return + } + const authToken = this.store.ensureAuthToken() + const signature = await getSubscriptionAuthorization(authToken) + await configureSubscription( + instance.blockchain_contract_name, + instance.blockchain_contract_address, + signer, + currentUser.wallet_address, + signature, + ) + this.subscriptionConfigured = true + } + async loadNextPage(maxId: string) { if (!this.profile) { return