diff --git a/apps/web/src/composables/users.ts b/apps/web/src/composables/users.ts index 7a49d864c..1335dc67e 100644 --- a/apps/web/src/composables/users.ts +++ b/apps/web/src/composables/users.ts @@ -4,8 +4,8 @@ import useSSV from '@/composables/ssv' import useWallet from '@/composables/wallet' import { onMounted, ref } from 'vue' import { User } from '@casimir/types' -import { Account } from '@casimir/types' -import { Currency } from '@casimir/types' +import { AddAccountOptions } from '@casimir/types' +import { RemoveAccountOptions } from '@casimir/types' import { ProviderString } from '@casimir/types' const { usersBaseURL, ethereumURL } = useEnvironment() @@ -60,19 +60,13 @@ export default function useUsers () { // subscribeToUserEvents() // }) - async function addAccount(provider: ProviderString, address: string, currency: Currency): Promise<{ error: boolean, message: string, data: User | null }> { - address = address.toLowerCase() - const accountToAdd = { - address, - walletProvider: provider, - ownerAddress: user.value?.Address, - } + async function addAccount(account: AddAccountOptions): Promise<{ error: boolean, message: string, data: User | null }> { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ account: accountToAdd }) + body: JSON.stringify({ account }) } const response = await fetch(`${usersBaseURL}/user/add-sub-account`, requestOptions) const { data: userAccount } = await response.json() @@ -80,8 +74,7 @@ export default function useUsers () { return { error: false, message: `Account added to user: ${userAccount}`, data: userAccount } } - // TODO: Refactor this next. 2/14 - async function removeAccount(provider: ProviderString, address: string, currency: Currency) { + async function removeAccount({ address, currency, ownerAddress, walletProvider }: RemoveAccountOptions) { address = address.toLowerCase() const requestOptions = { method: 'POST', @@ -89,13 +82,16 @@ export default function useUsers () { 'Content-Type': 'application/json' }, body: JSON.stringify({ - primaryAddress: user.value?.address, - provider, address, - currency + currency, + ownerAddress, + walletProvider, }) } - return await fetch(`${usersBaseURL}/user/remove-sub-account`, requestOptions) + const response = await fetch(`${usersBaseURL}/user/remove-sub-account`, requestOptions) + const { data: userAccount } = await response.json() + user.value = userAccount + return { error: false, message: `Account removed from user: ${userAccount}`, data: userAccount } } async function getMessage(address: string) { diff --git a/apps/web/src/composables/wallet.ts b/apps/web/src/composables/wallet.ts index d28a9a3a0..4771c7c31 100644 --- a/apps/web/src/composables/wallet.ts +++ b/apps/web/src/composables/wallet.ts @@ -124,25 +124,33 @@ export default function useWallet() { } loadingUserWallets.value = false } else { // Add account - console.log('already logged in! attempting to add account') + console.log('already logged in') + console.log('checking if account exists on user') const connectedAddress = await getConnectedAddressFromProvider(provider, currency) // TODO: Remove currency from here? Maybe not. const connectedCurrency = await detectCurrencyInProvider(provider, currency) as Currency const accountExists = user.value?.Accounts?.some((account: Account) => account.address === connectedAddress && account.wallet_provider === provider) + console.log('accountExists :>> ', accountExists) if (accountExists) { alert('Account already exists; setting provider, address, and currency') setSelectedProvider(provider) setSelectedAddress(connectedAddress) setSelectedCurrency(connectedCurrency) - return user.value } else { // If no, add account using users api - const response = await addAccount(provider, connectedAddress, connectedCurrency) + console.log('adding sub account') + const account = { + address: connectedAddress.toLowerCase(), + currency: connectedCurrency, + ownerAddress: user?.value?.Address.toLowerCase(), + walletProvider: provider + } + const response = await addAccount(account) // If api query is successful, set the user.value = to the response data (which should be the user) if (!response?.error) { setSelectedProvider(provider) setSelectedAddress(connectedAddress) setSelectedCurrency(connectedCurrency) - primaryAddress.value = response.data?.address as string + primaryAddress.value = response.data?.Address as string } } } @@ -236,11 +244,17 @@ export default function useWallet() { if (selectedAddress.value === primaryAddress.value) { return alert('Cannot remove primary account') } else if (ethersProviderList.includes(selectedProvider.value)) { - const result = await removeAccount(selectedProvider.value, selectedAddress.value, selectedCurrency.value) - const json = await result.json() - if (!json.error) { - setSelectedAddress(json.data.address) - json.data.accounts.forEach((account: Account) => { + const opts = { + address: selectedAddress.value, + currency: selectedCurrency.value, + ownerAddress: primaryAddress.value, + walletProvider: selectedProvider.value + } + const result = await removeAccount(opts) + console.log('result :>> ', result) + if (!result.error) { + setSelectedAddress(result.data.address) + result.data.Accounts.forEach((account: Account) => { if (account.address === selectedAddress.value) { setSelectedProvider(account.walletProvider as ProviderString) setSelectedCurrency(account.currency as Currency) diff --git a/services/users/src/providers/db.ts b/services/users/src/providers/db.ts index 8ee7a0613..a9f4e63e4 100644 --- a/services/users/src/providers/db.ts +++ b/services/users/src/providers/db.ts @@ -1,6 +1,6 @@ import { Postgres } from '@casimir/data' import { pascalCase } from '@casimir/helpers' -import { Account, User, UserAddedSuccess } from '@casimir/types' +import { Account, RemoveAccountOptions, User, UserAddedSuccess } from '@casimir/types' const postgres = new Postgres({ // These will become environment variables @@ -21,9 +21,9 @@ export default function useDB() { */ async function addAccount(account: Account, createdAt?: string) : Promise { if (!createdAt) createdAt = new Date().toISOString() - const { address, ownerAddress, walletProvider } = account - const text = 'INSERT INTO accounts (address, owner_address, wallet_provider, created_at) VALUES ($1, $2, $3, $4) RETURNING *;' - const params = [address, ownerAddress, walletProvider, createdAt] + const { address, currency, ownerAddress, walletProvider } = account + const text = 'INSERT INTO accounts (address, currency, owner_address, wallet_provider, created_at) VALUES ($1, $2, $3, $4, $5) RETURNING *;' + const params = [address, currency, ownerAddress, walletProvider, createdAt] const rows = await postgres.query(text, params) return rows[0] as Account } @@ -60,6 +60,21 @@ export default function useDB() { return formatResult(user) as User } + /** + * Remove an account. + * @param address - The account's address (pk) + * @param ownerAddress - The account's owner address + * @param walletProvider - The account's wallet provider + * @param currency - The account's currency + * @returns The removed account if found, otherwise undefined + */ + async function removeAccount({ address, currency, ownerAddress, walletProvider } : RemoveAccountOptions) { + const text = 'DELETE FROM accounts WHERE address = $1 AND owner_address = $2 AND wallet_provider = $3 AND currency = $4 RETURNING *;' + const params = [address, ownerAddress, walletProvider, currency] + const rows = await postgres.query(text, params) + return rows[0] as Account + } + /** * Add or update nonce for an address. * @param address - The address @@ -99,7 +114,7 @@ export default function useDB() { } } - return { addAccount, addUser, getUser, upsertNonce } + return { addAccount, addUser, getUser, removeAccount, upsertNonce } } /** diff --git a/services/users/src/routes/auth.ts b/services/users/src/routes/auth.ts index b6f50c306..e1d9ba551 100644 --- a/services/users/src/routes/auth.ts +++ b/services/users/src/routes/auth.ts @@ -42,6 +42,7 @@ router.post('/login', async (req: express.Request, res: express.Response) => { } const account = { address, + currency, ownerAddress: address, walletProvider: provider, } as Account diff --git a/services/users/src/routes/user.ts b/services/users/src/routes/user.ts index af78e43bd..52d40e969 100644 --- a/services/users/src/routes/user.ts +++ b/services/users/src/routes/user.ts @@ -5,7 +5,7 @@ import { SessionRequest } from 'supertokens-node/framework/express' import useDB from '../providers/db' const router = express.Router() -const { getUser, addAccount } = useDB() +const { addAccount, getUser, removeAccount } = useDB() router.get('/', verifySession(), async (req: SessionRequest, res: express.Response) => { const address = req.session?.getUserId() as string @@ -57,30 +57,32 @@ router.post('/add-sub-account', verifySession(), async (req: SessionRequest, res } }) -router.post('/remove-sub-account', verifySession(), async (req: express.Request, res: express.Response) => { +router.post('/remove-sub-account', verifySession(), async (req: SessionRequest, res: express.Response) => { try { - const { provider, address, currency } = req.body - let { primaryAddress } = req.body - primaryAddress = primaryAddress.toLowerCase() - const existingUser = userCollection.find(user => user.address === primaryAddress) - let accountedRemoved = false - if (existingUser) { - existingUser.accounts = existingUser.accounts?.filter(account => { - const notAddress = account.walletProvider !== provider || account.address !== address || account.currency !== currency - if (!notAddress) { - accountedRemoved = true - } else { - return account - } + console.log('REMOVING ACCOUNT!') + const { address, currency, ownerAddress, walletProvider } = req.body + const userSessionsAddress = req.session?.getUserId() + const validatedAddress = validateAddress(userSessionsAddress, ownerAddress) + if (!validatedAddress) { + res.setHeader('Content-Type', 'application/json') + res.status(200) + res.json({ + message: 'Address does not match session', + error: true, + data: null }) + return } - if (accountedRemoved) { + const accountRemoved = await removeAccount({ address, currency, ownerAddress, walletProvider }) + const user = await getUser(ownerAddress) + + if (accountRemoved) { res.setHeader('Content-Type', 'application/json') res.status(200) res.json({ message: 'Account removed', error: false, - data: existingUser + data: user }) } else { res.setHeader('Content-Type', 'application/json') @@ -88,7 +90,7 @@ router.post('/remove-sub-account', verifySession(), async (req: express.Request, res.json({ message: 'Account not found', error: true, - data: existingUser + data: user }) } } catch (err) {