Allow clients to create manalinks
This commit is contained in:
parent
2b37c2dd14
commit
12aceef4ca
|
@ -1,6 +1,6 @@
|
||||||
export type Manalink = {
|
export type Manalink = {
|
||||||
// The link to send: https://manifold.markets/send/{slug}
|
// The link to send: https://manifold.markets/send/{slug}
|
||||||
// Also functions as the unique identifier for the link.
|
// Also functions as the unique id for the link.
|
||||||
slug: string
|
slug: string
|
||||||
|
|
||||||
// Note: we assume both fromId and toId are of SourceType 'USER'
|
// Note: we assume both fromId and toId are of SourceType 'USER'
|
||||||
|
@ -11,10 +11,10 @@ export type Manalink = {
|
||||||
token: 'M$' // TODO: could send eg YES shares too??
|
token: 'M$' // TODO: could send eg YES shares too??
|
||||||
|
|
||||||
createdTime: number
|
createdTime: number
|
||||||
// If not set, the link is valid forever
|
// If set to Infinity, the link is valid forever
|
||||||
expiresTime?: number
|
expiresTime: number
|
||||||
// If not set, the link can be used infinitely
|
// If set to Infinity, the link can be used infinitely
|
||||||
maxUses?: number
|
maxUses: number
|
||||||
|
|
||||||
// Successful redemptions of the link
|
// Successful redemptions of the link
|
||||||
successes: Claim[]
|
successes: Claim[]
|
||||||
|
|
|
@ -85,5 +85,10 @@ service cloud.firestore {
|
||||||
match /txns/{txnId} {
|
match /txns/{txnId} {
|
||||||
allow read;
|
allow read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match /manalinks/{slug} {
|
||||||
|
allow read;
|
||||||
|
allow create, update: if request.auth.uid == request.resource.data.fromId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
40
web/lib/firebase/manalinks.ts
Normal file
40
web/lib/firebase/manalinks.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { setDoc } from 'firebase/firestore'
|
||||||
|
import { doc } from 'firebase/firestore'
|
||||||
|
import { Manalink } from '../../../common/manalink'
|
||||||
|
import { db } from './init'
|
||||||
|
import { customAlphabet } from 'nanoid'
|
||||||
|
|
||||||
|
export async function createManalink(data: {
|
||||||
|
fromId: string
|
||||||
|
amount: number
|
||||||
|
expiresTime: number
|
||||||
|
maxUses: number
|
||||||
|
}) {
|
||||||
|
const { fromId, amount, expiresTime, maxUses } = data
|
||||||
|
|
||||||
|
// At 100 IDs per hour, using this alphabet and 8 chars, there's a 1% chance of collision in 2 years
|
||||||
|
// See https://zelark.github.io/nano-id-cc/
|
||||||
|
const nanoid = customAlphabet(
|
||||||
|
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||||
|
8
|
||||||
|
)
|
||||||
|
const slug = nanoid()
|
||||||
|
|
||||||
|
if (amount <= 0 || isNaN(amount) || !isFinite(amount))
|
||||||
|
return { status: 'error', message: 'Invalid amount' }
|
||||||
|
|
||||||
|
const manalink: Manalink = {
|
||||||
|
slug,
|
||||||
|
fromId,
|
||||||
|
amount,
|
||||||
|
token: 'M$',
|
||||||
|
createdTime: Date.now(),
|
||||||
|
expiresTime,
|
||||||
|
maxUses,
|
||||||
|
successes: [],
|
||||||
|
failures: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const ref = doc(db, 'manalinks', slug)
|
||||||
|
await setDoc(ref, manalink)
|
||||||
|
}
|
|
@ -29,6 +29,7 @@
|
||||||
"gridjs": "5.0.2",
|
"gridjs": "5.0.2",
|
||||||
"gridjs-react": "5.0.2",
|
"gridjs-react": "5.0.2",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
|
"nanoid": "^3.3.4",
|
||||||
"next": "12.1.2",
|
"next": "12.1.2",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-confetti": "^6.0.1",
|
"react-confetti": "^6.0.1",
|
||||||
|
|
35
web/pages/send.tsx
Normal file
35
web/pages/send.tsx
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { Page } from '../components/page'
|
||||||
|
import { SEO } from '../components/SEO'
|
||||||
|
import { useUser } from '../hooks/use-user'
|
||||||
|
import { createManalink } from '../lib/firebase/manalinks'
|
||||||
|
|
||||||
|
export default function SendPage() {
|
||||||
|
const user = useUser()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<SEO
|
||||||
|
title="Send Mana"
|
||||||
|
description="Send mana to anyone via link!"
|
||||||
|
url="/send"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<h1>Send Mana</h1>
|
||||||
|
{user && (
|
||||||
|
<button
|
||||||
|
className="btn"
|
||||||
|
onClick={async () => {
|
||||||
|
await createManalink({
|
||||||
|
fromId: user.id,
|
||||||
|
amount: 1234,
|
||||||
|
expiresTime: Date.now() + 1000 * 60 * 60 * 24 * 7,
|
||||||
|
maxUses: Infinity,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create a new Manalink
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
}
|
|
@ -3793,6 +3793,11 @@ nanoid@^3.1.30:
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557"
|
||||||
integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==
|
integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==
|
||||||
|
|
||||||
|
nanoid@^3.3.4:
|
||||||
|
version "3.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||||
|
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
||||||
|
|
||||||
natural-compare@^1.4.0:
|
natural-compare@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user