variable downzaps
This commit is contained in:
parent
25d2c58559
commit
7d170a654f
|
@ -834,7 +834,7 @@ export default {
|
||||||
sats
|
sats
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dontLikeThis: async (parent, { id, hash, hmac }, { me, models }) => {
|
dontLikeThis: async (parent, { id, sats, hash, hmac }, { me, models }) => {
|
||||||
// need to make sure we are logged in
|
// need to make sure we are logged in
|
||||||
if (!me) {
|
if (!me) {
|
||||||
throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } })
|
throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } })
|
||||||
|
@ -856,7 +856,7 @@ export default {
|
||||||
|
|
||||||
const trx = [
|
const trx = [
|
||||||
models.$queryRaw`SELECT item_act(${Number(id)}::INTEGER,
|
models.$queryRaw`SELECT item_act(${Number(id)}::INTEGER,
|
||||||
${me.id}::INTEGER, 'DONT_LIKE_THIS', ${DONT_LIKE_THIS_COST}::INTEGER)`
|
${me.id}::INTEGER, 'DONT_LIKE_THIS', ${sats || DONT_LIKE_THIS_COST}::INTEGER)`
|
||||||
]
|
]
|
||||||
if (invoice) {
|
if (invoice) {
|
||||||
trx.unshift(models.$queryRaw`UPDATE users SET msats = msats + ${invoice.msatsReceived} WHERE id = ${invoice.user.id}`)
|
trx.unshift(models.$queryRaw`UPDATE users SET msats = msats + ${invoice.msatsReceived} WHERE id = ${invoice.user.id}`)
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default gql`
|
||||||
text: String!, url: String!, maxBid: Int!, status: String, logo: Int, hash: String, hmac: String): Item!
|
text: String!, url: String!, maxBid: Int!, status: String, logo: Int, hash: String, hmac: String): Item!
|
||||||
upsertPoll(id: ID, sub: String, title: String!, text: String, options: [String!]!, boost: Int, forward: [ItemForwardInput], hash: String, hmac: String): Item!
|
upsertPoll(id: ID, sub: String, title: String!, text: String, options: [String!]!, boost: Int, forward: [ItemForwardInput], hash: String, hmac: String): Item!
|
||||||
upsertComment(id:ID, text: String!, parentId: ID, hash: String, hmac: String): Item!
|
upsertComment(id:ID, text: String!, parentId: ID, hash: String, hmac: String): Item!
|
||||||
dontLikeThis(id: ID!, hash: String, hmac: String): Boolean!
|
dontLikeThis(id: ID!, sats: Int, hash: String, hmac: String): Boolean!
|
||||||
act(id: ID!, sats: Int, hash: String, hmac: String): ItemActResult!
|
act(id: ID!, sats: Int, hash: String, hmac: String): ItemActResult!
|
||||||
pollVote(id: ID!, hash: String, hmac: String): ID!
|
pollVote(id: ID!, hash: String, hmac: String): ID!
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { useShowModal } from './modal'
|
||||||
import { useToast } from './toast'
|
import { useToast } from './toast'
|
||||||
import { InvoiceModal, payOrLoginError } from './invoice'
|
import { InvoiceModal, payOrLoginError } from './invoice'
|
||||||
import { DONT_LIKE_THIS_COST } from '../lib/constants'
|
import { DONT_LIKE_THIS_COST } from '../lib/constants'
|
||||||
|
import ItemAct from './item-act'
|
||||||
|
|
||||||
export default function DontLikeThisDropdownItem ({ id }) {
|
export default function DontLikeThisDropdownItem ({ id }) {
|
||||||
const toaster = useToast()
|
const toaster = useToast()
|
||||||
|
@ -11,8 +12,8 @@ export default function DontLikeThisDropdownItem ({ id }) {
|
||||||
|
|
||||||
const [dontLikeThis] = useMutation(
|
const [dontLikeThis] = useMutation(
|
||||||
gql`
|
gql`
|
||||||
mutation dontLikeThis($id: ID!, $hash: String, $hmac: String) {
|
mutation dontLikeThis($id: ID!, $sats: Int, $hash: String, $hmac: String) {
|
||||||
dontLikeThis(id: $id, hash: $hash, hmac: $hmac)
|
dontLikeThis(id: $id, sats: $sats, hash: $hash, hmac: $hmac)
|
||||||
}`, {
|
}`, {
|
||||||
update (cache) {
|
update (cache) {
|
||||||
cache.modify({
|
cache.modify({
|
||||||
|
@ -31,11 +32,13 @@ export default function DontLikeThisDropdownItem ({ id }) {
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
await dontLikeThis({
|
showModal(onClose =>
|
||||||
variables: { id },
|
<ItemAct
|
||||||
optimisticResponse: { dontLikeThis: true }
|
onClose={() => {
|
||||||
})
|
onClose()
|
||||||
toaster.success('item flagged')
|
toaster.success('item flagged')
|
||||||
|
}} itemId={id} act={dontLikeThis} down
|
||||||
|
/>)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
if (payOrLoginError(error)) {
|
if (payOrLoginError(error)) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ const addCustomTip = (amount) => {
|
||||||
window.localStorage.setItem('custom-tips', JSON.stringify(customTips))
|
window.localStorage.setItem('custom-tips', JSON.stringify(customTips))
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ItemAct ({ onClose, itemId, act, strike }) {
|
export default function ItemAct ({ onClose, itemId, act, down, strike }) {
|
||||||
const inputRef = useRef(null)
|
const inputRef = useRef(null)
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
const [oValue, setOValue] = useState()
|
const [oValue, setOValue] = useState()
|
||||||
|
@ -59,7 +59,7 @@ export default function ItemAct ({ onClose, itemId, act, strike }) {
|
||||||
hmac
|
hmac
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await strike()
|
strike && await strike()
|
||||||
addCustomTip(Number(amount))
|
addCustomTip(Number(amount))
|
||||||
onClose()
|
onClose()
|
||||||
}, [act])
|
}, [act])
|
||||||
|
@ -88,7 +88,7 @@ export default function ItemAct ({ onClose, itemId, act, strike }) {
|
||||||
<Tips setOValue={setOValue} />
|
<Tips setOValue={setOValue} />
|
||||||
</div>
|
</div>
|
||||||
<div className='d-flex'>
|
<div className='d-flex'>
|
||||||
<SubmitButton variant='success' className='ms-auto mt-1 px-4' value='TIP'>zap</SubmitButton>
|
<SubmitButton variant={down ? 'danger' : 'success'} className='ms-auto mt-1 px-4' value='TIP'>{down && 'down '}zap</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
)
|
)
|
||||||
|
|
|
@ -136,7 +136,7 @@ export default function ItemInfo ({
|
||||||
<Link href={`/items/${item.id}/ots`} className='text-reset dropdown-item'>
|
<Link href={`/items/${item.id}/ots`} className='text-reset dropdown-item'>
|
||||||
ots timestamp
|
ots timestamp
|
||||||
</Link>}
|
</Link>}
|
||||||
{me && !item.meSats && !item.position && !item.meDontLike &&
|
{me && !item.meSats && !item.position &&
|
||||||
!item.mine && !item.deletedAt && <DontLikeThisDropdownItem id={item.id} />}
|
!item.mine && !item.deletedAt && <DontLikeThisDropdownItem id={item.id} />}
|
||||||
{item.mine && !item.position && !item.deletedAt &&
|
{item.mine && !item.position && !item.deletedAt &&
|
||||||
<DeleteDropdownItem itemId={item.id} type={item.title ? 'post' : 'comment'} />}
|
<DeleteDropdownItem itemId={item.id} type={item.title ? 'post' : 'comment'} />}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
DROP FUNCTION weighted_downvotes_after_act(item_id INTEGER, user_id INTEGER, sats INTEGER);
|
||||||
|
CREATE OR REPLACE FUNCTION weighted_downvotes_after_act(item_id INTEGER, user_id INTEGER, sats INTEGER) RETURNS INTEGER AS $$
|
||||||
|
DECLARE
|
||||||
|
user_trust DOUBLE PRECISION;
|
||||||
|
sats_past INTEGER;
|
||||||
|
multiplier DOUBLE PRECISION;
|
||||||
|
BEGIN
|
||||||
|
-- grab user's trust who is upvoting
|
||||||
|
SELECT trust INTO user_trust FROM users WHERE id = user_id;
|
||||||
|
|
||||||
|
-- in order to add this to weightedVotes, we need to do log((satsN+satsPrior)/satsPrior)
|
||||||
|
-- so compute sats prior
|
||||||
|
SELECT SUM(msats) / 1000 INTO sats_past
|
||||||
|
FROM "ItemAct"
|
||||||
|
WHERE "userId" = user_id AND "itemId" = item_id AND act IN ('DONT_LIKE_THIS');
|
||||||
|
|
||||||
|
IF sats_past IS NULL OR sats_past = 0 THEN
|
||||||
|
multiplier := LOG(sats);
|
||||||
|
ELSE
|
||||||
|
multiplier := LOG((sats+sats_past)/sats_past::FLOAT);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- update item
|
||||||
|
UPDATE "Item"
|
||||||
|
SET "weightedDownVotes" = "weightedDownVotes" + (user_trust * multiplier)
|
||||||
|
WHERE id = item_id AND "userId" <> user_id;
|
||||||
|
|
||||||
|
RETURN 0;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Update item_act to support multiple dont_like_this
|
||||||
|
CREATE OR REPLACE FUNCTION item_act(item_id INTEGER, user_id INTEGER, act "ItemActType", act_sats INTEGER)
|
||||||
|
RETURNS INTEGER
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
user_msats BIGINT;
|
||||||
|
act_msats BIGINT;
|
||||||
|
fee_msats BIGINT;
|
||||||
|
item_act_id INTEGER;
|
||||||
|
fwd_entry record; -- for loop iterator variable to iterate across forward recipients
|
||||||
|
fwd_msats BIGINT; -- for loop variable calculating how many msats to give each forward recipient
|
||||||
|
total_fwd_msats BIGINT := 0; -- accumulator to see how many msats have been forwarded for the act
|
||||||
|
BEGIN
|
||||||
|
PERFORM ASSERT_SERIALIZED();
|
||||||
|
|
||||||
|
act_msats := act_sats * 1000;
|
||||||
|
SELECT msats INTO user_msats FROM users WHERE id = user_id;
|
||||||
|
IF act_msats > user_msats THEN
|
||||||
|
RAISE EXCEPTION 'SN_INSUFFICIENT_FUNDS';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- deduct msats from actor
|
||||||
|
UPDATE users SET msats = msats - act_msats WHERE id = user_id;
|
||||||
|
|
||||||
|
IF act = 'TIP' THEN
|
||||||
|
-- call to influence weightedVotes ... we need to do this before we record the acts because
|
||||||
|
-- the priors acts are taken into account
|
||||||
|
PERFORM weighted_votes_after_tip(item_id, user_id, act_sats);
|
||||||
|
-- call to denormalize sats and commentSats
|
||||||
|
PERFORM sats_after_tip(item_id, user_id, act_msats);
|
||||||
|
|
||||||
|
-- take 10% and insert as FEE
|
||||||
|
fee_msats := CEIL(act_msats * 0.1);
|
||||||
|
act_msats := act_msats - fee_msats;
|
||||||
|
|
||||||
|
-- save the fee act into item_act_id so we can record referral acts
|
||||||
|
INSERT INTO "ItemAct" (msats, "itemId", "userId", act, created_at, updated_at)
|
||||||
|
VALUES (fee_msats, item_id, user_id, 'FEE', now_utc(), now_utc())
|
||||||
|
RETURNING id INTO item_act_id;
|
||||||
|
|
||||||
|
-- leave the rest as a tip
|
||||||
|
INSERT INTO "ItemAct" (msats, "itemId", "userId", act, created_at, updated_at)
|
||||||
|
VALUES (act_msats, item_id, user_id, 'TIP', now_utc(), now_utc());
|
||||||
|
|
||||||
|
-- denormalize bounty paid (if applicable)
|
||||||
|
PERFORM bounty_paid_after_act(item_id, user_id);
|
||||||
|
|
||||||
|
-- add sats to actees' balance and stacked count
|
||||||
|
FOR fwd_entry IN SELECT "userId", "pct" FROM "ItemForward" WHERE "itemId" = item_id
|
||||||
|
LOOP
|
||||||
|
-- fwd_msats represents the sats for this forward recipient from this particular tip action
|
||||||
|
fwd_msats := act_msats * fwd_entry.pct / 100;
|
||||||
|
-- keep track of how many msats have been forwarded, so we can give any remaining to OP
|
||||||
|
total_fwd_msats := fwd_msats + total_fwd_msats;
|
||||||
|
|
||||||
|
UPDATE users
|
||||||
|
SET msats = msats + fwd_msats, "stackedMsats" = "stackedMsats" + fwd_msats
|
||||||
|
WHERE id = fwd_entry."userId";
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
-- Give OP any remaining msats after forwards have been applied
|
||||||
|
IF act_msats - total_fwd_msats > 0 THEN
|
||||||
|
UPDATE users
|
||||||
|
SET msats = msats + act_msats - total_fwd_msats, "stackedMsats" = "stackedMsats" + act_msats - total_fwd_msats
|
||||||
|
WHERE id = (SELECT "userId" FROM "Item" WHERE id = item_id);
|
||||||
|
END IF;
|
||||||
|
ELSE -- BOOST, POLL, DONT_LIKE_THIS, STREAM
|
||||||
|
-- call to influence if DONT_LIKE_THIS weightedDownVotes
|
||||||
|
IF act = 'DONT_LIKE_THIS' THEN
|
||||||
|
PERFORM weighted_downvotes_after_act(item_id, user_id, act_sats);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
INSERT INTO "ItemAct" (msats, "itemId", "userId", act, created_at, updated_at)
|
||||||
|
VALUES (act_msats, item_id, user_id, act, now_utc(), now_utc())
|
||||||
|
RETURNING id INTO item_act_id;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- store referral effects
|
||||||
|
PERFORM referral_act(item_act_id);
|
||||||
|
|
||||||
|
RETURN 0;
|
||||||
|
END;
|
||||||
|
$$;
|
|
@ -11,7 +11,7 @@ function checkInvoice ({ boss, models, lnd }) {
|
||||||
try {
|
try {
|
||||||
inv = await getInvoice({ id: hash, lnd })
|
inv = await getInvoice({ id: hash, lnd })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
console.log(err, hash)
|
||||||
// on lnd related errors, we manually retry so we don't exponentially backoff
|
// on lnd related errors, we manually retry so we don't exponentially backoff
|
||||||
await boss.send('checkInvoice', { hash }, walletOptions)
|
await boss.send('checkInvoice', { hash }, walletOptions)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue