@@ -0,0 +1,105 @@ | |||
import SignetRequestController from '@/api/requests'; | |||
import { | |||
AuthenticationRequest, | |||
Bonus, | |||
CloseRewardFundRequest, | |||
ContributeRequest, | |||
CreateQueueRequest, | |||
CreateQueueResponse, | |||
CreateRewardFundRequest, | |||
GetBalanceRequest, | |||
GetBalanceResponse, | |||
GetContributionsRequest, | |||
GetContributionsResponse, | |||
GetQueueMembersRequest, | |||
GetQueueMembersResponse, | |||
GetQueuesResponse, | |||
GetRewardFundRequest, | |||
GetRewardFundResponse, | |||
GetRewardFundsRequest, | |||
GetRewardFundsResponse, | |||
LoginResponse, | |||
SuccessResponse, | |||
} from '@/api/types'; | |||
const controller = new SignetRequestController(); | |||
export const register = (username: string, password: string) => controller.post<SuccessResponse, AuthenticationRequest>('Register', { | |||
username, | |||
password, | |||
}); | |||
export const login = (username: string, password: string) => controller.post<LoginResponse, AuthenticationRequest>('Login', { | |||
username, | |||
password, | |||
}); | |||
export const getRewardFunds = (offset: number) => controller.post<GetRewardFundsResponse, GetRewardFundsRequest>('GetRewardFunds', { offset }); | |||
export const getQueues = () => controller.post<GetQueuesResponse, null>('GetQueues', null); | |||
export const getQueueMembers = (id: number) => controller.post<GetQueueMembersResponse, GetQueueMembersRequest>('GetQueueMembers', { id }); | |||
export const createQueue = (name: string) => controller.post<CreateQueueResponse, CreateQueueRequest>('CreateQueue', { name }); | |||
export const createRewardFund = ( | |||
asset: string, | |||
fundWallet: string, | |||
sellingWallet: string, | |||
issuerWallet: string, | |||
memo: string, | |||
minContribution: number, | |||
title: string, | |||
description: string, | |||
bonuses: Bonus[], | |||
queueID?: number | null | undefined, | |||
) => controller.post<SuccessResponse, CreateRewardFundRequest>('CreateRewardFund', { | |||
asset, | |||
fundWallet, | |||
sellingWallet, | |||
issuerWallet, | |||
memo, | |||
minContribution, | |||
title, | |||
description, | |||
bonuses, | |||
queueID, | |||
}); | |||
export const deleteRewardFund = (id: number, close: boolean) => controller.post< | |||
SuccessResponse, CloseRewardFundRequest | |||
>( | |||
'CloseRewardFund', | |||
{ | |||
id, | |||
close, | |||
}, | |||
); | |||
export const getRewardFund = (id: number, consolidateContributions: boolean) => controller.post<GetRewardFundResponse, GetRewardFundRequest>('GetRewardFund', { | |||
id, | |||
consolidateContributions, | |||
}); | |||
export const getContributions = ( | |||
id: number, | |||
offset: number, | |||
forDate: string | undefined, | |||
consolidateContributions: boolean, | |||
) => controller.post<GetContributionsResponse, GetContributionsRequest>( | |||
'GetContributions', | |||
{ | |||
id, | |||
offset, | |||
forDate, | |||
consolidateContributions, | |||
}, | |||
); | |||
export const getBalance = (secretKey: string) => controller.post<GetBalanceResponse, GetBalanceRequest>('GetBalance', { secretKey }); | |||
export const contribute = (privateKey: string, amount: number, rewardFund: number) => controller.post<SuccessResponse, ContributeRequest>('Contribute', { | |||
privateKey, | |||
amount, | |||
rewardFund, | |||
}); |
@@ -1,3 +1,5 @@ | |||
import store from '@/store'; | |||
const setHeaders = (headers: HeadersInit | undefined, token: string | undefined) => { | |||
if (!headers && !!token) { | |||
return { Authorization: `Bearer ${token}` }; | |||
@@ -6,24 +8,24 @@ const setHeaders = (headers: HeadersInit | undefined, token: string | undefined) | |||
return headers; | |||
} | |||
if (!!headers && !!token) { | |||
return { ...headers, Authorization: `Bearer ${token}` }; | |||
return { | |||
...headers, | |||
Authorization: `Bearer ${token}`, | |||
}; | |||
} | |||
return {}; | |||
}; | |||
class SignetRequestController { | |||
token?: string = undefined; | |||
constructor(token?: string) { | |||
this.token = token; | |||
} | |||
get = async <T>(endpoint: string): Promise<T | null> => { | |||
const resp = await fetch( | |||
`/api/${endpoint}`, | |||
{ | |||
method: 'GET', | |||
headers: setHeaders(undefined, this.token), | |||
headers: setHeaders( | |||
undefined, | |||
store.getters.getToken, | |||
), | |||
}, | |||
); | |||
if (resp.status === 404) { | |||
@@ -38,7 +40,10 @@ class SignetRequestController { | |||
{ | |||
method: 'POST', | |||
body: JSON.stringify(payload), | |||
headers: setHeaders({ 'Content-Type': 'application/json' }, this.token), | |||
headers: setHeaders( | |||
{ 'Content-Type': 'application/json' }, | |||
store.getters.getToken, | |||
), | |||
}, | |||
); | |||
if (resp.status === 404) { | |||
@@ -47,17 +47,14 @@ import { | |||
watch, | |||
} from 'vue'; | |||
import { | |||
GetQueueMembersRequest, | |||
GetQueueMembersResponse, | |||
GetQueuesResponse, | |||
Queue, | |||
RewardFund, | |||
} from '@/api/types'; | |||
import Draggable from 'vuedraggable'; | |||
import SignetRequestController from '@/api/requests'; | |||
import store from '@/store'; | |||
const controller = new SignetRequestController(store.getters.getToken); | |||
import { | |||
getQueueMembers, | |||
getQueues, | |||
} from '@/api/composed'; | |||
// eslint-disable-next-line no-undef | |||
const emits = defineEmits(['selected', 'created']); | |||
@@ -69,9 +66,9 @@ const drag = ref(false); | |||
const queues = ref([] as Queue[]); | |||
const fetchQueues = async () => { | |||
const v = await controller.post<GetQueuesResponse, null>('GetQueues', null); | |||
if (v) { | |||
queues.value = v.queues; | |||
const resp = await getQueues(); | |||
if (resp) { | |||
queues.value = resp.queues; | |||
} | |||
}; | |||
@@ -86,7 +83,7 @@ const createdQueue = () => { | |||
}; | |||
const populateQueueMembers = async (id: number) => { | |||
const resp = await controller.post<GetQueueMembersResponse, GetQueueMembersRequest>('GetQueueMembers', { id }); | |||
const resp = await getQueueMembers(id); | |||
queueMembers.value = resp?.members; | |||
}; | |||
@@ -14,7 +14,6 @@ import FundView from '@/views/FundView.vue'; | |||
import AddFundView from '@/views/AddFundView.vue'; | |||
import hasPermission from '@/lib/auth'; | |||
import SignetRequestController from '@/api/requests'; | |||
import store from '@/store'; | |||
const routes: Array<RouteRecordRaw> = [ | |||
{ | |||
@@ -42,7 +41,7 @@ const routes: Array<RouteRecordRaw> = [ | |||
meta: { | |||
requiredRights: Privileges.AdminPlus, | |||
accessible: async () => { | |||
const controller = new SignetRequestController(store.getters.getToken); | |||
const controller = new SignetRequestController(); | |||
const canProceed = await controller.post<SuccessResponse, null>('/UsersExist', null); | |||
return canProceed?.success; | |||
}, | |||
@@ -66,23 +66,23 @@ | |||
import SignetRequestController from '@/api/requests'; | |||
import { | |||
Bonus, | |||
CreateQueueRequest, | |||
CreateQueueResponse, | |||
CreateRewardFundRequest, | |||
SuccessResponse, | |||
} from '@/api/types'; | |||
import { ref } from 'vue'; | |||
import store from '@/store'; | |||
import { useRouter } from 'vue-router'; | |||
import FundTierInput from '@/components/FundTierInput.vue'; | |||
import { sanitize } from '@/lib/helpers'; | |||
import EditQueue from '@/components/EditQueue.vue'; | |||
import { | |||
createQueue, | |||
createRewardFund, | |||
} from '@/api/composed'; | |||
import { sanitize } from '@/lib/helpers'; | |||
const router = useRouter(); | |||
document.title = 'Beignet - Add Fund'; | |||
const controller = new SignetRequestController(store.getters.getToken); | |||
const controller = new SignetRequestController(); | |||
const title = ref(''); | |||
const description = ref(''); | |||
@@ -111,10 +111,10 @@ const saveBonuses = (evt: Bonus[]) => { | |||
bonuses.value = evt; | |||
}; | |||
const createQueue = async () => { | |||
const doCreateQueue = async () => { | |||
if (!queueName.value) return null; | |||
const resp = ref(undefined as CreateQueueResponse | undefined); | |||
resp.value = await controller.post<CreateQueueResponse, CreateQueueRequest>('CreateQueue', { name: queueName.value }) ?? undefined; | |||
resp.value = await createQueue(queueName.value) ?? undefined; | |||
if (resp.value?.id) { | |||
return resp.value?.id; | |||
} | |||
@@ -129,22 +129,22 @@ const submit = async () => { | |||
requesting.value = true; | |||
const forQueue = ref(undefined as null | number | undefined); | |||
if (queueSelection.value === -1) { | |||
forQueue.value = await createQueue(); | |||
forQueue.value = await doCreateQueue(); | |||
} else { | |||
forQueue.value = queueSelection.value; | |||
} | |||
const resp = await controller.post<SuccessResponse, CreateRewardFundRequest>('CreateRewardFund', { | |||
asset: asset.value, | |||
fundWallet: sanitize(fundWallet.value), | |||
sellingWallet: sanitize(sellWallet.value), | |||
issuerWallet: sanitize(issuerWallet.value), | |||
memo: sanitize(memo.value), | |||
minContribution: minContribution.value, | |||
title: sanitize(title.value), | |||
description: sanitize(description.value), | |||
bonuses: bonuses.value, | |||
queueID: forQueue.value, | |||
}); | |||
const resp = await createRewardFund( | |||
asset.value, | |||
sanitize(fundWallet.value), | |||
sanitize(sellWallet.value), | |||
sanitize(issuerWallet.value), | |||
sanitize(memo.value), | |||
minContribution.value, | |||
sanitize(title.value), | |||
sanitize(description.value), | |||
bonuses.value, | |||
forQueue.value, | |||
); | |||
requesting.value = false; | |||
if (!resp) throw new Error('Could not get response for fund creation'); | |||
@@ -193,18 +193,10 @@ import { | |||
} from 'vue-router'; | |||
import { | |||
Bonus, | |||
CloseRewardFundRequest, | |||
ContributeRequest, | |||
Contribution, | |||
FundInfo, | |||
GetBalanceRequest, | |||
GetBalanceResponse, | |||
GetContributionsRequest, | |||
GetContributionsResponse, | |||
GetRewardFundRequest, | |||
GetRewardFundResponse, | |||
Privileges, | |||
SuccessResponse, | |||
} from '@/api/types'; | |||
import { | |||
computed, | |||
@@ -213,7 +205,6 @@ import { | |||
watch, | |||
} from 'vue'; | |||
import { useWebSocket } from '@vueuse/core'; | |||
import SignetRequestController from '@/api/requests'; | |||
import store from '@/store'; | |||
import { | |||
sanitize, | |||
@@ -222,8 +213,13 @@ import { | |||
import * as luxon from 'luxon'; | |||
import hasPermission from '@/lib/auth'; | |||
import ErrorDisplay, { SignetError } from '@/components/ErrorDisplay.vue'; | |||
const controller = new SignetRequestController(store.getters.getToken); | |||
import { | |||
contribute, | |||
deleteRewardFund, | |||
getBalance, | |||
getContributions, | |||
getRewardFund, | |||
} from '@/api/composed'; | |||
const route = useRoute(); | |||
const router = useRouter(); | |||
@@ -245,17 +241,9 @@ const selectedDate = ref(undefined as string | undefined); | |||
const allowDelete = ref(false); | |||
const deleteFund = async () => { | |||
if (allowDelete.value) { | |||
const deleted = await controller.post<SuccessResponse, CloseRewardFundRequest>( | |||
'CloseRewardFund', | |||
{ | |||
id: identifier, | |||
close: true, | |||
}, | |||
); | |||
if (deleted && deleted.success) { | |||
await router.push('/'); | |||
} | |||
const deleted = await deleteRewardFund(identifier, allowDelete.value); | |||
if (deleted && deleted.success) { | |||
await router.push('/'); | |||
} | |||
}; | |||
@@ -276,10 +264,7 @@ const fundDetails = ref([{ | |||
val: '', | |||
}]); | |||
fund.value = await controller.post<GetRewardFundResponse, GetRewardFundRequest>('GetRewardFund', { | |||
id: identifier, | |||
consolidateContributions: enableConsolidation.value, | |||
}); | |||
fund.value = await getRewardFund(identifier, enableConsolidation.value); | |||
if (!fund.value) { | |||
router.push('/'); | |||
throw new Error('Fund not found'); | |||
@@ -394,17 +379,7 @@ document.title = `Beignet - ${fund.value.fundInfo.title}`; | |||
watch(selectedDate, async (newVal) => { | |||
offset.value = 0; | |||
const conts = await controller.post< | |||
GetContributionsResponse, GetContributionsRequest | |||
>( | |||
'GetContributions', | |||
{ | |||
id: identifier, | |||
offset: offset.value, | |||
forDate: newVal, | |||
consolidateContributions: enableConsolidation.value, | |||
}, | |||
); | |||
const conts = await getContributions(identifier, offset.value, newVal, enableConsolidation.value); | |||
if (!fund.value) throw new Error('Fund not found'); | |||
if (!conts) throw new Error('Contributions not found'); | |||
contributions.value = conts.list; | |||
@@ -420,14 +395,11 @@ const loadMoreIfNeeded = async (e: Event) => { | |||
if (canLoadMore()) { | |||
contributionsLoading.value = true; | |||
const moreContribs = await controller.post<GetContributionsResponse, GetContributionsRequest>( | |||
'GetContributions', | |||
{ | |||
id: identifier, | |||
offset: offset.value, | |||
forDate: selectedDate.value, | |||
consolidateContributions: enableConsolidation.value, | |||
}, | |||
const moreContribs = await getContributions( | |||
identifier, | |||
offset.value, | |||
selectedDate.value, | |||
enableConsolidation.value, | |||
); | |||
if (!moreContribs) throw new Error('Contributions not found'); | |||
offset.value += moreContribs.list.length; | |||
@@ -451,7 +423,7 @@ const { | |||
const queryAccount = async () => { | |||
if (pk.value && pk.value.startsWith('S')) { | |||
loading.value.balance = true; | |||
const resp = await controller.post<GetBalanceResponse, GetBalanceRequest>('GetBalance', { secretKey: pk.value }); | |||
const resp = await getBalance(pk.value); | |||
if (resp === null) { | |||
unknownAcct.value = true; | |||
acctBalance.value = undefined; | |||
@@ -475,11 +447,7 @@ const makeContribution = async () => { | |||
if (unknownAcct.value) return; | |||
if (!loading.value.contribution && pk.value && amt.value && amt.value <= amountAvailable.value) { | |||
loading.value.contribution = true; | |||
await controller.post<SuccessResponse, ContributeRequest>('Contribute', { | |||
privateKey: sanitize(pk.value), | |||
amount: amt.value, | |||
rewardFund: fund.value.fundInfo.id, | |||
}); | |||
await contribute(sanitize(pk.value), amt.value, fund.value.fundInfo.id); | |||
loading.value.contribution = false; | |||
pk.value = ''; | |||
amt.value = undefined; | |||
@@ -488,16 +456,11 @@ const makeContribution = async () => { | |||
watch(enableConsolidation, async () => { | |||
offset.value = 0; | |||
const conts = await controller.post< | |||
GetContributionsResponse, GetContributionsRequest | |||
>( | |||
'GetContributions', | |||
{ | |||
id: identifier, | |||
offset: offset.value, | |||
forDate: selectedDate.value, | |||
consolidateContributions: enableConsolidation.value, | |||
}, | |||
const conts = await getContributions( | |||
identifier, | |||
offset.value, | |||
selectedDate.value, | |||
enableConsolidation.value, | |||
); | |||
if (!fund.value) throw new Error('Fund not found'); | |||
if (!conts) throw new Error('Contributions not found'); | |||
@@ -18,22 +18,18 @@ | |||
</template> | |||
<script setup lang="ts"> | |||
import { | |||
GetRewardFundsRequest, | |||
GetRewardFundsResponse, | |||
} from '@/api/types'; | |||
import { ref } from 'vue'; | |||
import SignetRequestController from '@/api/requests'; | |||
import store from '@/store'; | |||
import FundLink from '@/components/FundLink.vue'; | |||
const controller = new SignetRequestController(store.getters.getToken); | |||
import { getRewardFunds } from '@/api/composed'; | |||
const offset = ref(0); | |||
const response = await controller.post<GetRewardFundsResponse, GetRewardFundsRequest>('GetRewardFunds', { offset: offset.value }); | |||
const response = await getRewardFunds(offset.value); | |||
if (!response) throw new Error('Could not get reward funds'); | |||
const { total, rewardFunds } = response; | |||
const { | |||
total, | |||
rewardFunds, | |||
} = response; | |||
offset.value = total; | |||
</script> | |||
@@ -21,13 +21,7 @@ | |||
import { ref } from 'vue'; | |||
import { useRouter } from 'vue-router'; | |||
import store from '@/store'; | |||
import { | |||
AuthenticationRequest, | |||
LoginResponse, | |||
} from '@/api/types'; | |||
import SignetRequestController from '@/api/requests'; | |||
const controller = new SignetRequestController(store.getters.getToken); | |||
import { login } from '@/api/composed'; | |||
const router = useRouter(); | |||
@@ -35,7 +29,7 @@ const username = ref(''); | |||
const password = ref(''); | |||
const submit = async () => { | |||
const resp = await controller.post<LoginResponse, AuthenticationRequest>('Login', { username: username.value, password: password.value }); | |||
const resp = await login(username.value, password.value); | |||
if (!resp) throw new Error('Could not get response from login'); | |||
if (resp.token !== null) { | |||
sessionStorage.setItem('jwt', JSON.stringify({ token: resp.token })); | |||
@@ -19,15 +19,8 @@ | |||
<script setup lang="ts"> | |||
import { ref } from 'vue'; | |||
import { | |||
AuthenticationRequest, | |||
SuccessResponse, | |||
} from '@/api/types'; | |||
import SignetRequestController from '@/api/requests'; | |||
import store from '@/store'; | |||
import { useRouter } from 'vue-router'; | |||
const controller = new SignetRequestController(store.getters.getToken); | |||
import { register } from '@/api/composed'; | |||
const router = useRouter(); | |||
@@ -36,7 +29,7 @@ const password = ref(''); | |||
const success = ref(false); | |||
const submit = async () => { | |||
const resp = await controller.post<SuccessResponse, AuthenticationRequest>('Register', { username: username.value, password: password.value }); | |||
const resp = await register(username.value, password.value); | |||
if (!resp) throw new Error('Could not get response from registration'); | |||
success.value = resp.success; | |||
if (success.value) { | |||
@@ -2,12 +2,19 @@ import { expect } from 'chai'; | |||
import { shallowMount } from '@vue/test-utils'; | |||
import HelloWorld from '@/components/HelloWorld.vue'; | |||
// TODO: Not sure why this isn't working | |||
// vi.mock('@/api/composed', () => ({ | |||
// getRewardFunds: vi.fn(() => []), | |||
// })); | |||
describe('HelloWorld.vue', () => { | |||
it('renders props.msg when passed', () => { | |||
const msg = 'new message'; | |||
const wrapper = shallowMount(HelloWorld, { | |||
props: { msg }, | |||
}); | |||
expect(wrapper.text()).to.include(msg); | |||
expect(wrapper.text()) | |||
.to | |||
.include(msg); | |||
}); | |||
}); |