feat: patron contract
This commit is contained in:
parent
ed3e0b2e07
commit
1b2aad7d48
|
|
@ -46,7 +46,7 @@
|
|||
"canvas-confetti": "^1.6.0",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "1.2.1",
|
||||
"crossbell.js": "0.16.7",
|
||||
"crossbell.js": "0.16.13",
|
||||
"dayjs": "1.11.7",
|
||||
"dotenv": "16.0.3",
|
||||
"emoji-mart": "5.5.2",
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ specifiers:
|
|||
chroma-js: ^2.4.2
|
||||
clsx: 1.2.1
|
||||
cross-spawn: 7.0.3
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
dayjs: 1.11.7
|
||||
dotenv: 16.0.3
|
||||
emoji-mart: 5.5.2
|
||||
|
|
@ -163,7 +163,7 @@ dependencies:
|
|||
canvas-confetti: 1.6.0
|
||||
chroma-js: 2.4.2
|
||||
clsx: 1.2.1
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
dayjs: 1.11.7
|
||||
dotenv: 16.0.3
|
||||
emoji-mart: 5.5.2
|
||||
|
|
@ -1676,7 +1676,7 @@ packages:
|
|||
canvas-confetti: 1.6.0
|
||||
check-password-strength: 2.0.7
|
||||
classnames: 2.3.2
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
detect-browser: 5.3.0
|
||||
embla-carousel-react: 7.1.0_react@18.2.0
|
||||
immer: 9.0.19
|
||||
|
|
@ -1691,7 +1691,6 @@ packages:
|
|||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
- bufferutil
|
||||
- node-fetch
|
||||
- react-dom
|
||||
- react-native
|
||||
- supports-color
|
||||
|
|
@ -1708,12 +1707,11 @@ packages:
|
|||
dependencies:
|
||||
'@crossbell/indexer': 0.0.41_mesmmewwopkmkl7hvhwkhlmhve
|
||||
'@crossbell/util-hooks': 0.0.41_biqbaboplfbrettd7655fr4n2y
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
react: 18.2.0
|
||||
wagmi: 0.11.7_osprwltll6etshz2owvseumghu
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- node-fetch
|
||||
- react-dom
|
||||
- react-native
|
||||
- supports-color
|
||||
|
|
@ -1727,14 +1725,13 @@ packages:
|
|||
wagmi: ^0.11
|
||||
dependencies:
|
||||
'@tanstack/react-query': 4.24.10_biqbaboplfbrettd7655fr4n2y
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
dayjs: 1.11.7
|
||||
lodash.compact: 3.0.1
|
||||
lru-cache: 7.18.1
|
||||
wagmi: 0.11.7_osprwltll6etshz2owvseumghu
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- node-fetch
|
||||
- react
|
||||
- react-dom
|
||||
- react-native
|
||||
|
|
@ -1742,6 +1739,10 @@ packages:
|
|||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@crossbell/ipfs-fetch/0.0.15:
|
||||
resolution: {integrity: sha512-AYGDrwiSKqCGNDi0mEPP1k+96loWik+Pd40xH0MzRNM4RtCutPbwm4o+Sj5iWu0tlHoQC2bTs1XcufsLiv+WYw==}
|
||||
dev: false
|
||||
|
||||
/@crossbell/notification/0.0.41_ogut4lnwvlvmg3jumn6qr7hh6u:
|
||||
resolution: {integrity: sha512-5KjSzUC8SMEx7IHQyeSfLuUEAGI+NBmROxPwx4GAp/hqGIHYtuaz1vDqcINv9OzwnChkmNDuYucz9A1wVe33sg==}
|
||||
peerDependencies:
|
||||
|
|
@ -1766,7 +1767,6 @@ packages:
|
|||
- bufferutil
|
||||
- ethers
|
||||
- immer
|
||||
- node-fetch
|
||||
- react-dom
|
||||
- react-native
|
||||
- supports-color
|
||||
|
|
@ -1786,7 +1786,7 @@ packages:
|
|||
'@crossbell/util-metadata': 0.0.41
|
||||
'@tanstack/react-query': 4.24.10_biqbaboplfbrettd7655fr4n2y
|
||||
classnames: 2.3.2
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
facepaint: 1.2.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
|
|
@ -1798,7 +1798,6 @@ packages:
|
|||
- '@types/react'
|
||||
- bufferutil
|
||||
- ethers
|
||||
- node-fetch
|
||||
- react-native
|
||||
- supports-color
|
||||
- typescript
|
||||
|
|
@ -1816,11 +1815,10 @@ packages:
|
|||
react: ^18
|
||||
dependencies:
|
||||
'@tanstack/react-query': 4.24.10_biqbaboplfbrettd7655fr4n2y
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
react: 18.2.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- node-fetch
|
||||
- react-dom
|
||||
- react-native
|
||||
- supports-color
|
||||
|
|
@ -1832,10 +1830,9 @@ packages:
|
|||
dependencies:
|
||||
'@crossbell/util-ethers': 0.0.41
|
||||
'@fastify/deepmerge': 1.3.0
|
||||
crossbell.js: 0.16.7
|
||||
crossbell.js: 0.16.13
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- node-fetch
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
|
@ -6351,6 +6348,23 @@ packages:
|
|||
which: 2.0.2
|
||||
dev: true
|
||||
|
||||
/crossbell.js/0.16.13:
|
||||
resolution: {integrity: sha512-nX1IBr6XKi0NtgV8SAtQwWhyebUA4zwlpIauFFNRsprScSE1dNbcsSKscwX9AXFB49ai6VhYOvPNpG+k8YjGww==}
|
||||
dependencies:
|
||||
'@crossbell/ipfs-fetch': 0.0.15
|
||||
async-retry: 1.3.3
|
||||
browser-or-node: 2.1.1
|
||||
ethers: 5.7.2
|
||||
fetch-undici: 3.0.1
|
||||
p-limit: 3.1.0
|
||||
ts-mixer: 6.0.3
|
||||
web3-providers-ws: 1.8.2
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/crossbell.js/0.16.2:
|
||||
resolution: {integrity: sha512-Rgy1v6EmXy0ou9JVRezMHfUp3L9OHAub0d8jExoN3iJPQtvd0jopy0QNONL0ShvIJxTsiCwM1rg9SAA5sw6gZQ==}
|
||||
dependencies:
|
||||
|
|
@ -6368,24 +6382,6 @@ packages:
|
|||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/crossbell.js/0.16.7:
|
||||
resolution: {integrity: sha512-qr6QRdpPKNVsv7pjazqJGmz2s92MBaH+jaf91u/hgNCYILFKOIAuntnpKGLmP/r3HMccopUUwxxBSH/W9QrAxg==}
|
||||
dependencies:
|
||||
async-retry: 1.3.3
|
||||
browser-or-node: 2.1.1
|
||||
ethers: 5.7.2
|
||||
fetch-undici: 3.0.1
|
||||
is-ipfs: 6.0.2
|
||||
p-limit: 3.1.0
|
||||
ts-mixer: 6.0.3
|
||||
web3-providers-ws: 1.8.2
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- node-fetch
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/crypto-random-string/2.0.0:
|
||||
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -7624,7 +7620,7 @@ packages:
|
|||
resolution: {integrity: sha512-UHHu1HqW22ZhK6C/1Zmjf7mQpOwPwLYZ+xcsOgpzistONU8QqvCop6Od29p/kw1GUVoq2Ihu6ItpKLtlojx4FQ==}
|
||||
engines: {node: '>=16'}
|
||||
dependencies:
|
||||
undici: 5.20.0
|
||||
undici: 5.21.0
|
||||
dev: false
|
||||
|
||||
/file-entry-cache/6.0.1:
|
||||
|
|
@ -8065,7 +8061,7 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
inherits: 2.0.4
|
||||
readable-stream: 3.6.1
|
||||
readable-stream: 3.6.2
|
||||
safe-buffer: 5.2.1
|
||||
dev: false
|
||||
|
||||
|
|
@ -11385,6 +11381,15 @@ packages:
|
|||
util-deprecate: 1.0.2
|
||||
dev: false
|
||||
|
||||
/readable-stream/3.6.2:
|
||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
inherits: 2.0.4
|
||||
string_decoder: 1.3.0
|
||||
util-deprecate: 1.0.2
|
||||
dev: false
|
||||
|
||||
/readdirp/3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
|
@ -12859,8 +12864,8 @@ packages:
|
|||
jiti: 1.17.1
|
||||
dev: true
|
||||
|
||||
/undici/5.20.0:
|
||||
resolution: {integrity: sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==}
|
||||
/undici/5.21.0:
|
||||
resolution: {integrity: sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==}
|
||||
engines: {node: '>=12.18'}
|
||||
dependencies:
|
||||
busboy: 1.6.0
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@ import { useTranslation } from "next-i18next"
|
|||
import { HeartIcon } from "@heroicons/react/24/solid"
|
||||
import { cn } from "~/lib/utils"
|
||||
import { Modal } from "~/components/ui/Modal"
|
||||
import { useState } from "react"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { BoxRadio } from "~/components/ui/BoxRadio"
|
||||
import { CharacterCard } from "~/components/common/CharacterCard"
|
||||
import { QuestionMarkCircleIcon } from "@heroicons/react/24/outline"
|
||||
import { Tabs } from "../ui/Tabs"
|
||||
import { useTipCharacter, useGetTips } from "~/queries/site"
|
||||
import { useAccountState } from "@crossbell/connect-kit"
|
||||
import { toast } from "react-hot-toast"
|
||||
import confetti from "canvas-confetti"
|
||||
|
||||
export const PatronModal: React.FC<{
|
||||
site: Profile | undefined | null
|
||||
|
|
@ -16,6 +20,11 @@ export const PatronModal: React.FC<{
|
|||
setOpen: (open: boolean) => void
|
||||
}> = ({ site, open, setOpen }) => {
|
||||
const { t } = useTranslation("common")
|
||||
const tipCharacter = useTipCharacter()
|
||||
// const tips = useGetTips({
|
||||
// toCharacterId: site?.metadata?.proof,
|
||||
// })
|
||||
// console.log(tips.data)
|
||||
|
||||
const radios = [
|
||||
{
|
||||
|
|
@ -45,10 +54,48 @@ export const PatronModal: React.FC<{
|
|||
|
||||
const [value, setValue] = useState(radios[1].value!)
|
||||
|
||||
const currentCharacterId = useAccountState(
|
||||
(s) => s.computed.account?.characterId,
|
||||
)
|
||||
|
||||
const submit = () => {
|
||||
console.log(value)
|
||||
if (currentCharacterId && site?.metadata?.proof && parseInt(value)) {
|
||||
tipCharacter.mutate({
|
||||
fromCharacterId: currentCharacterId,
|
||||
toCharacterId: site?.metadata?.proof,
|
||||
amount: parseInt(value),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const submitRef = useRef<HTMLButtonElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!tipCharacter.isSuccess) {
|
||||
if (submitRef.current?.getBoundingClientRect()) {
|
||||
confetti({
|
||||
particleCount: 150,
|
||||
spread: 70,
|
||||
origin: {
|
||||
x:
|
||||
(submitRef.current.getBoundingClientRect().left +
|
||||
submitRef.current.getBoundingClientRect().width / 2 || 0.5) /
|
||||
window.innerWidth,
|
||||
y:
|
||||
(submitRef.current.getBoundingClientRect().top || 0.5) /
|
||||
window.innerHeight,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [tipCharacter.isSuccess, t, site?.name])
|
||||
|
||||
useEffect(() => {
|
||||
if (tipCharacter.isError) {
|
||||
toast.error(t("Failed to become a patron"))
|
||||
}
|
||||
}, [tipCharacter.isError, t])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
|
|
@ -99,7 +146,16 @@ export const PatronModal: React.FC<{
|
|||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="primary" className="w-full" onClick={submit}>
|
||||
<Button
|
||||
variant="primary"
|
||||
className="w-full"
|
||||
onClick={submit}
|
||||
style={{
|
||||
height: "2.5rem",
|
||||
}}
|
||||
isLoading={tipCharacter.isLoading}
|
||||
ref={submitRef}
|
||||
>
|
||||
{t("Become a patron to {{name}}", {
|
||||
name: site?.name,
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ export const BoxRadio: React.FC<{
|
|||
<div className="grid gap-4 grid-cols-3">
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<div key={item.value} className="relative w-full min-h-[80px]">
|
||||
<div
|
||||
key={item.value || item.text}
|
||||
className="relative w-full min-h-[80px]"
|
||||
>
|
||||
{item.value ? (
|
||||
<>
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -511,3 +511,25 @@ export async function getStat({ characterId }: { characterId: string }) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function tipCharacter(
|
||||
input: {
|
||||
fromCharacterId: string | number
|
||||
toCharacterId: string | number
|
||||
amount: number
|
||||
},
|
||||
contract: Contract,
|
||||
) {
|
||||
return await contract?.tipCharacter(
|
||||
input.fromCharacterId,
|
||||
input.toCharacterId,
|
||||
input.amount,
|
||||
)
|
||||
}
|
||||
|
||||
export async function getTips(input: { toCharacterId: string | number }) {
|
||||
return await indexer?.getTips({
|
||||
toCharacterId: input.toCharacterId,
|
||||
tokenAddress: "0xAfB95CC0BD320648B3E8Df6223d9CDD05EbeDC64",
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,3 +302,35 @@ export const useGetStat = (
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function useTipCharacter() {
|
||||
const queryClient = useQueryClient()
|
||||
const contract = useContract()
|
||||
const mutation = useMutation(
|
||||
async (payload: Parameters<typeof siteModel.tipCharacter>[0]) => {
|
||||
return siteModel.tipCharacter(payload, contract)
|
||||
},
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries([
|
||||
"getTips",
|
||||
{
|
||||
toCharacterId: variables.toCharacterId,
|
||||
},
|
||||
])
|
||||
},
|
||||
},
|
||||
)
|
||||
return mutation
|
||||
}
|
||||
|
||||
export const useGetTips = (data: { toCharacterId?: string }) => {
|
||||
return useQuery(["getTips", data], async () => {
|
||||
if (!data.toCharacterId) {
|
||||
return null
|
||||
}
|
||||
return siteModel.getTips({
|
||||
toCharacterId: data.toCharacterId,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue