withdrawl => withdrawal/withdraw
This commit is contained in:
parent
2703f1b987
commit
79cb2d5c27
|
@ -5,7 +5,7 @@
|
||||||
The site is written in javascript using Next.js, a React framework. The backend API is provided via graphql. The database is postgresql modelled with prisma. We use lnd for the lightning node which we connect to through a tor http tunnel. A customized Bootstrap theme is used for styling.
|
The site is written in javascript using Next.js, a React framework. The backend API is provided via graphql. The database is postgresql modelled with prisma. We use lnd for the lightning node which we connect to through a tor http tunnel. A customized Bootstrap theme is used for styling.
|
||||||
|
|
||||||
# processes
|
# processes
|
||||||
There are two. 1. the web app and 2. walletd, which checks and polls lnd for all pending invoice/withdrawl statuses in case the web process dies.
|
There are two. 1. the web app and 2. walletd, which checks and polls lnd for all pending invoice/withdrawal statuses in case the web process dies.
|
||||||
|
|
||||||
# wallet transaction safety
|
# wallet transaction safety
|
||||||
To ensure user balances are kept sane, all wallet updates are run in serializable transactions at the database level. Because prisma has relatively poor support for transactions all wallet touching code is written in plpgsql stored procedures and can be found in the prisma/migrations folder.
|
To ensure user balances are kept sane, all wallet updates are run in serializable transactions at the database level. Because prisma has relatively poor support for transactions all wallet touching code is written in plpgsql stored procedures and can be found in the prisma/migrations folder.
|
||||||
|
|
|
@ -18,10 +18,10 @@ async function serialize (models, call) {
|
||||||
bail(new Error('wallet balance transaction is not serializable'))
|
bail(new Error('wallet balance transaction is not serializable'))
|
||||||
}
|
}
|
||||||
if (error.message.includes('SN_CONFIRMED_WITHDRAWL_EXISTS')) {
|
if (error.message.includes('SN_CONFIRMED_WITHDRAWL_EXISTS')) {
|
||||||
bail(new Error('withdrawl invoice already confirmed (to withdrawl again create a new invoice)'))
|
bail(new Error('withdrawal invoice already confirmed (to withdraw again create a new invoice)'))
|
||||||
}
|
}
|
||||||
if (error.message.includes('SN_PENDING_WITHDRAWL_EXISTS')) {
|
if (error.message.includes('SN_PENDING_WITHDRAWL_EXISTS')) {
|
||||||
bail(new Error('withdrawl invoice exists and is pending'))
|
bail(new Error('withdrawal invoice exists and is pending'))
|
||||||
}
|
}
|
||||||
if (error.message.includes('40001')) {
|
if (error.message.includes('40001')) {
|
||||||
throw new Error('wallet balance serialization failure - retry again')
|
throw new Error('wallet balance serialization failure - retry again')
|
||||||
|
|
|
@ -39,7 +39,7 @@ export default {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (wdrwl.user.id !== me.id) {
|
if (wdrwl.user.id !== me.id) {
|
||||||
throw new AuthenticationError('not ur withdrawl')
|
throw new AuthenticationError('not ur withdrawal')
|
||||||
}
|
}
|
||||||
|
|
||||||
return wdrwl
|
return wdrwl
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { gql, useMutation } from '@apollo/client'
|
||||||
import { LnQRSkeleton } from '../components/lnqr'
|
import { LnQRSkeleton } from '../components/lnqr'
|
||||||
import LayoutCenter from '../components/layout-center'
|
import LayoutCenter from '../components/layout-center'
|
||||||
import InputGroup from 'react-bootstrap/InputGroup'
|
import InputGroup from 'react-bootstrap/InputGroup'
|
||||||
import { WithdrawlSkeleton } from './withdrawls/[id]'
|
import { WithdrawlSkeleton } from './withdrawals/[id]'
|
||||||
import { useMe } from '../components/me'
|
import { useMe } from '../components/me'
|
||||||
|
|
||||||
export default function Wallet () {
|
export default function Wallet () {
|
||||||
|
@ -38,8 +38,8 @@ export function WalletForm () {
|
||||||
<Button variant='success'>fund</Button>
|
<Button variant='success'>fund</Button>
|
||||||
</Link>
|
</Link>
|
||||||
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
||||||
<Link href='/wallet?type=withdrawl'>
|
<Link href='/wallet?type=withdraw'>
|
||||||
<Button variant='success'>withdrawl</Button>
|
<Button variant='success'>withdraw</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -129,7 +129,7 @@ export function WithdrawlForm () {
|
||||||
schema={WithdrawlSchema}
|
schema={WithdrawlSchema}
|
||||||
onSubmit={async ({ invoice, maxFee }) => {
|
onSubmit={async ({ invoice, maxFee }) => {
|
||||||
const { data } = await createWithdrawl({ variables: { invoice, maxFee: Number(maxFee) } })
|
const { data } = await createWithdrawl({ variables: { invoice, maxFee: Number(maxFee) } })
|
||||||
router.push(`/withdrawls/${data.createWithdrawl.id}`)
|
router.push(`/withdrawals/${data.createWithdrawl.id}`)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
|
@ -144,7 +144,7 @@ export function WithdrawlForm () {
|
||||||
required
|
required
|
||||||
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
||||||
/>
|
/>
|
||||||
<SubmitButton variant='success' className='mt-2'>withdrawl</SubmitButton>
|
<SubmitButton variant='success' className='mt-2'>withdraw</SubmitButton>
|
||||||
</Form>
|
</Form>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- add withdrawal as user
|
||||||
|
INSERT INTO "users" ("name") VALUES ('withdrawal');
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- add withdrawals as user
|
||||||
|
INSERT INTO "users" ("name") VALUES ('withdrawals');
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- withdraw users
|
||||||
|
INSERT INTO "users" ("name") VALUES ('withdraw');
|
||||||
|
INSERT INTO "users" ("name") VALUES ('withdraws');
|
Loading…
Reference in New Issue