diff --git a/components/views/friends/add/Add.vue b/components/views/friends/add/Add.vue index be273fe744..70c5794c24 100644 --- a/components/views/friends/add/Add.vue +++ b/components/views/friends/add/Add.vue @@ -13,6 +13,7 @@ import { debounce } from 'lodash' import { Friend } from '~/types/ui/friends' import ServerProgram from '~/libraries/Solana/ServerProgram/ServerProgram' import SolanaManager from '~/libraries/Solana/SolanaManager/SolanaManager' +import UsersProgram from '~/libraries/Solana/UsersProgram/UsersProgram' export default Vue.extend({ components: { @@ -68,9 +69,9 @@ export default Vue.extend({ this.error = '' try { const $SolanaManager: SolanaManager = Vue.prototype.$SolanaManager - const serverProgram: ServerProgram = new ServerProgram($SolanaManager) + const usersProgram: UsersProgram = new UsersProgram($SolanaManager) - const friend = await serverProgram.getUser(new PublicKey(accountID)) + const friend = await usersProgram.getUserInfo(accountID) if (!friend) { this.error = this.$t('friends.not_found') as string return diff --git a/config.ts b/config.ts index d13fe958ef..fc9584e81c 100644 --- a/config.ts +++ b/config.ts @@ -49,6 +49,8 @@ export const Config = { friendsProgramId: 'BxX6o2HG5DWrJt2v8GMSWNG2V2NtxNbAUF3wdE5Ao5gS', defaultCommitment: 'confirmed' as Commitment, defaultPreflightCommitment: 'confirmed' as Commitment, + usersPrograId: '7MaC2xrAmmFsuRBEkD6BEL3eJpXCmaikYhLM3eKBPhAH', + groupchatsPrograId: 'bJhvwTYCkQceANgeShZ4xaxUqEBPsV8e1NgRnLRymxs', }, // Realms are just different chains we support realms: [ diff --git a/cypress b/cypress index 7eb9ca784a..7ab496ab2e 160000 --- a/cypress +++ b/cypress @@ -1 +1 @@ -Subproject commit 7eb9ca784a65ed982a6ed407839863832827fd03 +Subproject commit 7ab496ab2ea9303b97fe0e2ba6ebaab9ee7401a8 diff --git a/libraries/Solana/FriendsProgram/FriendsProgram.ts b/libraries/Solana/FriendsProgram/FriendsProgram.ts index 9f0c866b6c..657a903bb8 100644 --- a/libraries/Solana/FriendsProgram/FriendsProgram.ts +++ b/libraries/Solana/FriendsProgram/FriendsProgram.ts @@ -637,17 +637,17 @@ export default class FriendsProgram extends EventEmitter { const { connection } = this.solana - const userAccount = this.solana.getUserAccount() - if (!userAccount) { + const payerAccount = this.solana.getActiveAccount() + if (!payerAccount) { throw new Error('User account not found') } const fromKeyAndStatus = base58( - Buffer.from([...userAccount.publicKey.toBytes(), status]), + Buffer.from([...payerAccount.publicKey.toBytes(), status]), ) const statusAndToKey = base58( - Buffer.from([status, ...userAccount.publicKey.toBytes()]), + Buffer.from([status, ...payerAccount.publicKey.toBytes()]), ) const outgoing = await connection.getProgramAccounts(FRIENDS_PROGRAM_ID, { @@ -693,8 +693,8 @@ export default class FriendsProgram extends EventEmitter { } const { connection } = this.solana - const userAccount = this.solana.getUserAccount() - if (!userAccount) { + const payerAccount = this.solana.getActiveAccount() + if (!payerAccount) { throw new Error('User account not found') } @@ -703,7 +703,7 @@ export default class FriendsProgram extends EventEmitter { // formatted that way // [32 bytes (sender public key)][1 byte (status)][32 bytes (recipient public key)] const incomingRequestBytes = base58( - Buffer.from([FriendStatus.PENDING, ...userAccount.publicKey.toBytes()]), + Buffer.from([FriendStatus.PENDING, ...payerAccount.publicKey.toBytes()]), ) const incomingRequestsFilter: GetProgramAccountsFilter = { @@ -723,7 +723,7 @@ export default class FriendsProgram extends EventEmitter { // This filter checks the sender public key (our) and the status // [32 bytes (sender public key)][1 byte (status)][32 bytes (recipient public key)] const newFriendFromOutgoingBytes = base58( - Buffer.from([...userAccount.publicKey.toBytes(), FriendStatus.ACCEPTED]), + Buffer.from([...payerAccount.publicKey.toBytes(), FriendStatus.ACCEPTED]), ) const newFriendFromOutgoingFilter: GetProgramAccountsFilter = { @@ -741,7 +741,7 @@ export default class FriendsProgram extends EventEmitter { // This filter checks the sender public key (our) and the status // [32 bytes (sender public key)][1 byte (status)][32 bytes (recipient public key)] const friendRequestDeniedBytes = base58( - Buffer.from([...userAccount.publicKey.toBytes(), FriendStatus.REFUSED]), + Buffer.from([...payerAccount.publicKey.toBytes(), FriendStatus.REFUSED]), ) const friendRequestDeniedFilter: GetProgramAccountsFilter = { @@ -761,7 +761,7 @@ export default class FriendsProgram extends EventEmitter { // This filter checks the sender public key (our) and the status // [32 bytes (sender public key)][1 byte (status)][32 bytes (recipient public key)] const friendRequestRemovedBytes = base58( - Buffer.from([...userAccount.publicKey.toBytes(), FriendStatus.REMOVED]), + Buffer.from([...payerAccount.publicKey.toBytes(), FriendStatus.REMOVED]), ) const friendRequestRemovedFilter: GetProgramAccountsFilter = { @@ -776,7 +776,7 @@ export default class FriendsProgram extends EventEmitter { ) const friendRequestRemovedMirroredBytes = base58( - Buffer.from([FriendStatus.REMOVED, ...userAccount.publicKey.toBytes()]), + Buffer.from([FriendStatus.REMOVED, ...payerAccount.publicKey.toBytes()]), ) const friendRequestRemovedMirroredFilter: GetProgramAccountsFilter = { diff --git a/libraries/Solana/UsersProgram/UsersProgram.ts b/libraries/Solana/UsersProgram/UsersProgram.ts new file mode 100644 index 0000000000..a320ab7f3e --- /dev/null +++ b/libraries/Solana/UsersProgram/UsersProgram.ts @@ -0,0 +1,235 @@ +import { EventEmitter } from 'events' +import { Program, Wallet, web3, utils, Provider } from '@project-serum/anchor' +import { Users, IDL } from './UsersProgram.types' + +import Solana from '~/libraries/Solana/SolanaManager/SolanaManager' +import { Config } from '~/config' + +const { PublicKey, SystemProgram } = web3 + +export const USERS_PROGRAM_ID = new PublicKey(Config.solana.usersPrograId) + +const userSeed = Buffer.from(utils.bytes.utf8.encode('user')) + +export default class UsersProgram extends EventEmitter { + solana?: Solana + program?: Program + subscriptions?: { [eventName: string]: number } + + constructor(solana: Solana) { + super() + if (solana) { + this.init(solana) + } + } + + /** + * @method init + * Initializes the class with the SolanaManager instance + * @param solana SolanaManager instance + */ + init(solana: Solana) { + this.solana = solana + + const payer = this._getPayer() + + const provider = new Provider(this.solana.connection, new Wallet(payer), { + commitment: Config.solana.defaultCommitment, + }) + + this.program = new Program( + IDL, + USERS_PROGRAM_ID.toBase58(), + provider, + ) + } + + /** + * @method _userPDAPublicKey + * Computes a user PDA for the given Public Key + * @param address String version of the Public Key + * @returns the computed PDA + */ + protected async _userPDAPublicKey(address: string) { + const program = this._getProgram() + + const user = new PublicKey(address) + + return utils.publicKey.findProgramAddressSync( + [user.toBytes(), userSeed], + program.programId, + ) + } + + /** + * @method _getProgram + * Returns the anchor program instance for group chat + * @returns the anchor program instance + */ + protected _getProgram() { + if (!this.program) { + throw new Error('Group Chat Manager not initialized') + } + + return this.program + } + + /** + * @method _getPayer + * Retrieve the active account from Solana wallet + * @returns the payer account + */ + protected _getPayer() { + const payer = this.solana?.getActiveAccount() + + if (!payer) { + throw new Error('Missing payer') + } + + return payer + } + + /** + * @method _getUpdateOpts + * Get multiple information useful for the update functions + * @returns program instance, payer account, user info and user PDA + */ + protected async _getUpdateOpts() { + const program = this._getProgram() + const payer = this._getPayer() + + const userPDA = await this._userPDAPublicKey(payer.publicKey.toBase58()) + + const userInfo = await this.getCurrentUserInfo() + + if (!userInfo) { + throw new Error('Non existent account') + } + + return { program, payer, userPDA, userInfo } + } + + /** + * @method create + * Create a new user + * @param name Username + * @param photoHash Profile picture IPFS hash + * @param statusMessage Status message string + */ + async create(name: string, photoHash: string, statusMessage: string) { + // Throws if the program is not set + const program = this._getProgram() + + // Throws if the payer is not set + const payer = this._getPayer() + + const userPDA = utils.publicKey.findProgramAddressSync( + [payer.publicKey.toBytes(), userSeed], + program.programId, + ) + + await program.rpc.create(name, photoHash, statusMessage, { + accounts: { + user: userPDA[0], + signer: payer.publicKey, + payer: payer.publicKey, + systemProgram: SystemProgram.programId, + }, + signers: [payer], + }) + } + + /** + * @method getUserInfo + * Fetch the user information from the user program + * @param address string representation of the Public key + * @returns the parsed user info + */ + async getUserInfo(address: string) { + const program = this._getProgram() + + const userPDA = await this._userPDAPublicKey(address) + + const userInfo = await program.account.user.fetchNullable(userPDA[0]) + + if (!userInfo) { + return null + } + + return { + name: userInfo.name as string, + photoHash: userInfo.photoHash as string, + status: userInfo.status as string, + } + } + + /** + * @method getCurrentUserInfo + * Returns the user info for the active account + * @returns the user info object for the current + */ + async getCurrentUserInfo() { + const payer = this._getPayer() + + return this.getUserInfo(payer.publicKey.toBase58()) + } + + /** + * @method setName + * Allow the user to update the user name + * @param name user name + * @returns the transaction to update the status message + */ + async setName(name: string) { + const { program, userPDA, payer } = await this._getUpdateOpts() + + return program.rpc.setName(name, { + accounts: { + user: userPDA[0], + signer: payer.publicKey, + payer: payer.publicKey, + }, + signers: [payer], + }) + } + + /** + * @method setPhotoHash + * Allow the user to update the profile picture + * @param photoHash profile picture IPFS hash + * @returns the transaction to update the photo hash + */ + async setPhotoHash(photoHash: string) { + const { program, userPDA, payer } = await this._getUpdateOpts() + + return program.rpc.setPhotoHash(photoHash, { + accounts: { + user: userPDA[0], + signer: payer.publicKey, + payer: payer.publicKey, + }, + signers: [payer], + }) + } + + /** + * @method setStatusMessage + * Allow the user to update the status message + * @param statusMessage status message + * @returns the transaction to update the status message + */ + async setStatusMessage(statusMessage: string) { + const { program, userPDA, payer } = await this._getUpdateOpts() + + return program.rpc.setStatus(statusMessage, { + accounts: { + user: userPDA[0], + signer: payer.publicKey, + payer: payer.publicKey, + }, + signers: [payer], + }) + } +} + +export type UserInfo = Awaited> diff --git a/libraries/Solana/UsersProgram/UsersProgram.types.ts b/libraries/Solana/UsersProgram/UsersProgram.types.ts new file mode 100644 index 0000000000..cf4758337f --- /dev/null +++ b/libraries/Solana/UsersProgram/UsersProgram.types.ts @@ -0,0 +1,315 @@ +export type Users = { + version: '0.1.0' + name: 'users' + instructions: [ + { + name: 'create' + accounts: [ + { + name: 'user' + isMut: true + isSigner: false + }, + { + name: 'signer' + isMut: false + isSigner: true + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + }, + ] + args: [ + { + name: 'name' + type: 'string' + }, + { + name: 'photoHash' + type: 'string' + }, + { + name: 'status' + type: 'string' + }, + ] + }, + { + name: 'setName' + accounts: [ + { + name: 'user' + isMut: true + isSigner: false + }, + { + name: 'signer' + isMut: false + isSigner: true + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + ] + args: [ + { + name: 'name' + type: 'string' + }, + ] + }, + { + name: 'setPhotoHash' + accounts: [ + { + name: 'user' + isMut: true + isSigner: false + }, + { + name: 'signer' + isMut: false + isSigner: true + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + ] + args: [ + { + name: 'photoHash' + type: 'string' + }, + ] + }, + { + name: 'setStatus' + accounts: [ + { + name: 'user' + isMut: true + isSigner: false + }, + { + name: 'signer' + isMut: false + isSigner: true + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + ] + args: [ + { + name: 'status' + type: 'string' + }, + ] + }, + ] + accounts: [ + { + name: 'user' + type: { + kind: 'struct' + fields: [ + { + name: 'name' + type: 'string' + }, + { + name: 'photoHash' + type: 'string' + }, + { + name: 'status' + type: 'string' + }, + ] + } + }, + ] + errors: [ + { + code: 6000 + name: 'WrongPrivileges' + msg: 'User cannot perform this action' + }, + { + code: 6001 + name: 'PayerMismatch' + msg: 'Account was not created by provided user' + }, + ] +} + +export const IDL: Users = { + version: '0.1.0', + name: 'users', + instructions: [ + { + name: 'create', + accounts: [ + { + name: 'user', + isMut: true, + isSigner: false, + }, + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'name', + type: 'string', + }, + { + name: 'photoHash', + type: 'string', + }, + { + name: 'status', + type: 'string', + }, + ], + }, + { + name: 'setName', + accounts: [ + { + name: 'user', + isMut: true, + isSigner: false, + }, + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + ], + args: [ + { + name: 'name', + type: 'string', + }, + ], + }, + { + name: 'setPhotoHash', + accounts: [ + { + name: 'user', + isMut: true, + isSigner: false, + }, + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + ], + args: [ + { + name: 'photoHash', + type: 'string', + }, + ], + }, + { + name: 'setStatus', + accounts: [ + { + name: 'user', + isMut: true, + isSigner: false, + }, + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + ], + args: [ + { + name: 'status', + type: 'string', + }, + ], + }, + ], + accounts: [ + { + name: 'user', + type: { + kind: 'struct', + fields: [ + { + name: 'name', + type: 'string', + }, + { + name: 'photoHash', + type: 'string', + }, + { + name: 'status', + type: 'string', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'WrongPrivileges', + msg: 'User cannot perform this action', + }, + { + code: 6001, + name: 'PayerMismatch', + msg: 'Account was not created by provided user', + }, + ], +} diff --git a/nuxt.config.js b/nuxt.config.js index 200be575f3..c6dd9885e7 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -2,6 +2,9 @@ import { defineNuxtConfig } from '@nuxt/bridge' import pkg from './package.json' export default defineNuxtConfig({ + alias: { + tslib: 'tslib/tslib.es6.js', + }, bridge: { nitro: false, }, diff --git a/package.json b/package.json index e250672290..b475497a74 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@nuxtjs/pwa": "^3.3.5", "@nuxtjs/style-resources": "^1.0.0", "@nuxtjs/toast": "^3.3.1", + "@project-serum/anchor": "0.18.2", "@solana/web3.js": "^1.25.0", "@tensorflow/tfjs": "^3.8.0", "@textile/hub": "^6.3.0", diff --git a/store/accounts/actions.ts b/store/accounts/actions.ts index 9b6aa393a6..73af82555c 100644 --- a/store/accounts/actions.ts +++ b/store/accounts/actions.ts @@ -7,8 +7,8 @@ import { UserRegistrationPayload, } from './types' import Crypto from '~/libraries/Crypto/Crypto' -import ServerProgram from '~/libraries/Solana/ServerProgram/ServerProgram' import SolanaManager from '~/libraries/Solana/SolanaManager/SolanaManager' +import UsersProgram from '~/libraries/Solana/UsersProgram/UsersProgram' import { ActionsArguments, RootState } from '~/types/store/store' import TextileManager from '~/libraries/Textile/TextileManager' @@ -142,7 +142,7 @@ export default { await $SolanaManager.initializeFromMnemonic(mnemonic) - const userAccount = $SolanaManager.getUserAccount() + const userAccount = $SolanaManager.getActiveAccount() if (!userAccount) { throw new Error(AccountsError.USER_DERIVATION_FAILED) @@ -150,9 +150,9 @@ export default { commit('setActiveAccount', userAccount?.publicKey.toBase58()) - const serverProgram: ServerProgram = new ServerProgram($SolanaManager) + const usersProgram: UsersProgram = new UsersProgram($SolanaManager) - const userInfo = await serverProgram.getUser(userAccount.publicKey) + const userInfo = await usersProgram.getCurrentUserInfo() if (userInfo === null) { throw new Error(AccountsError.USER_NOT_REGISTERED) @@ -226,9 +226,9 @@ export default { throw new Error(AccountsError.USER_DERIVATION_FAILED) } - const serverProgram: ServerProgram = new ServerProgram($SolanaManager) + const usersProgram: UsersProgram = new UsersProgram($SolanaManager) - const userInfo = await serverProgram.getUser(userAccount.publicKey) + const userInfo = await usersProgram.getCurrentUserInfo() if (userInfo) { commit('setRegistrationStatus', RegistrationStatus.REGISTERED) @@ -253,7 +253,7 @@ export default { const imagePath = await uploadPicture(userData.image) - await serverProgram.createUser(userData.name, imagePath, userData.status) + await usersProgram.create(userData.name, imagePath, userData.status) commit('setRegistrationStatus', RegistrationStatus.REGISTERED) diff --git a/store/friends/actions.ts b/store/friends/actions.ts index 4d59a6492d..09c1f60e9e 100644 --- a/store/friends/actions.ts +++ b/store/friends/actions.ts @@ -10,7 +10,6 @@ import { import Crypto from '~/libraries/Crypto/Crypto' import SolanaManager from '~/libraries/Solana/SolanaManager/SolanaManager' import FriendsProgram from '~/libraries/Solana/FriendsProgram/FriendsProgram' -import ServerProgram from '~/libraries/Solana/ServerProgram/ServerProgram' import { FriendAccount, FriendsEvents, @@ -24,8 +23,10 @@ import { OutgoingRequest, } from '~/types/ui/friends' import { ActionsArguments } from '~/types/store/store' -import { RawUser } from '~/types/ui/user' import TextileManager from '~/libraries/Textile/TextileManager' +import UsersProgram, { + UserInfo, +} from '~/libraries/Solana/UsersProgram/UsersProgram' export default { /** @@ -39,23 +40,21 @@ export default { const friendsProgram: FriendsProgram = new FriendsProgram($SolanaManager) - const serverProgram: ServerProgram = new ServerProgram($SolanaManager) + const usersProgram: UsersProgram = new UsersProgram($SolanaManager) const { incoming, outgoing } = await friendsProgram.getFriendAccountsByStatus(FriendStatus.PENDING) const incomingRequests = await Promise.all( incoming.map(async (account) => { - const userInfo = await serverProgram.getUser( - new PublicKey(account.from), - ) + const userInfo = await usersProgram.getUserInfo(account.from) return friendAccountToIncomingRequest(account, userInfo) }), ) const outgoingRequests = await Promise.all( outgoing.map(async (account) => { - const userInfo = await serverProgram.getUser(new PublicKey(account.to)) + const userInfo = await usersProgram.getUserInfo(account.to) return friendAccountToOutgoingRequest(account, userInfo) }), ) @@ -109,7 +108,7 @@ export default { friendAccount: FriendAccount, ) { const $SolanaManager: SolanaManager = Vue.prototype.$SolanaManager - const serverProgram: ServerProgram = new ServerProgram($SolanaManager) + const usersProgram: UsersProgram = new UsersProgram($SolanaManager) const $Crypto: Crypto = Vue.prototype.$Crypto // Check if the request was originally sent by the current user (outgoing) @@ -128,16 +127,18 @@ export default { friendKey, encryptedTextilePubkey, ) - const rawUser = await serverProgram.getUser(new PublicKey(friendKey)) - if (!rawUser) { + + const userInfo = await usersProgram.getUserInfo(friendKey) + + if (!userInfo) { throw new Error(FriendsError.FRIEND_INFO_NOT_FOUND) } const friend: Omit = { account: friendAccount, - name: rawUser.name, - profilePicture: rawUser.photoHash, - status: rawUser.status, + name: userInfo.name, + profilePicture: userInfo.photoHash, + status: userInfo.status, encryptedTextilePubkey, textilePubkey, item: {}, @@ -184,7 +185,7 @@ export default { const friendsProgram: FriendsProgram = new FriendsProgram($SolanaManager) - const serverProgram: ServerProgram = new ServerProgram($SolanaManager) + const usersProgram: UsersProgram = new UsersProgram($SolanaManager) const userAccount = $SolanaManager.getActiveAccount() @@ -194,9 +195,7 @@ export default { FriendsEvents.NEW_REQUEST, async (account) => { if (account) { - const userInfo = await serverProgram.getUser( - new PublicKey(account.from), - ) + const userInfo = await usersProgram.getUserInfo(account.from) commit( 'addIncomingRequest', friendAccountToIncomingRequest(account, userInfo), @@ -257,7 +256,7 @@ export default { const $SolanaManager: SolanaManager = Vue.prototype.$SolanaManager const $Crypto: Crypto = Vue.prototype.$Crypto const $TextileManager: TextileManager = Vue.prototype.$TextileManager - const serverProgram: ServerProgram = new ServerProgram($SolanaManager) + const usersProgram: UsersProgram = new UsersProgram($SolanaManager) const textilePublicKey = $TextileManager.getIdentityPublicKey() @@ -271,16 +270,10 @@ export default { throw new Error(AccountsError.PAYER_NOT_PRESENT) } - const userAccount = await $SolanaManager.getUserAccount() - - if (!userAccount) { - throw new Error(AccountsError.USER_DERIVATION_FAILED) - } - const friendsProgram: FriendsProgram = new FriendsProgram($SolanaManager) const friendAccountKey = await friendsProgram.computeFriendAccountKey( - userAccount.publicKey, + payerAccount.publicKey, friendToKey, ) @@ -289,7 +282,7 @@ export default { const friendAccountMirroredKey = await friendsProgram.computeFriendAccountKey( friendToKey, - userAccount.publicKey, + payerAccount.publicKey, ) let friendAccountMirroredInfo = await friendsProgram.getFriend( @@ -298,7 +291,7 @@ export default { if (!friendAccountInfo) { friendAccountInfo = await friendsProgram.createFriend( - userAccount.publicKey, + payerAccount.publicKey, friendToKey, ) } @@ -306,7 +299,7 @@ export default { if (!friendAccountMirroredInfo) { friendAccountMirroredInfo = await friendsProgram.createFriend( friendToKey, - userAccount.publicKey, + payerAccount.publicKey, ) } @@ -336,7 +329,7 @@ export default { const transactionHash = await friendsProgram.createFriendRequest( friendAccountKey, friendAccountMirroredKey, - userAccount, + payerAccount, friendToKey, Buffer.from(encryptedTextilePublicKey.padStart(128, '0')), ) @@ -347,9 +340,7 @@ export default { ) if (parsedFriendRequest) { - const userInfo = await serverProgram.getUser( - new PublicKey(parsedFriendRequest.to), - ) + const userInfo = await usersProgram.getUserInfo(parsedFriendRequest.to) commit( 'addOutgoingRequest', friendAccountToOutgoingRequest(parsedFriendRequest, userInfo), @@ -384,12 +375,6 @@ export default { throw new Error(AccountsError.PAYER_NOT_PRESENT) } - const userAccount = await $SolanaManager.getUserAccount() - - if (!userAccount) { - throw new Error(AccountsError.USER_DERIVATION_FAILED) - } - const friendsProgram: FriendsProgram = new FriendsProgram($SolanaManager) commit('updateIncomingRequest', { ...friendRequest, pending: true }) @@ -398,7 +383,7 @@ export default { const computedFriendAccountKey = await friendsProgram.computeFriendAccountKey( new PublicKey(account.from), - userAccount.publicKey, + payerAccount.publicKey, ) const friendFromKey = friendRequest.account.from @@ -415,7 +400,7 @@ export default { const transactionId = await friendsProgram.acceptFriendRequest( computedFriendAccountKey, new PublicKey(account.from), - userAccount, + payerAccount, Buffer.from(encryptedIdentityPublicKey.padStart(128, '0')), ) @@ -441,12 +426,6 @@ export default { throw new Error(AccountsError.PAYER_NOT_PRESENT) } - const userAccount = await $SolanaManager.getUserAccount() - - if (!userAccount) { - throw new Error(AccountsError.USER_DERIVATION_FAILED) - } - const friendsProgram: FriendsProgram = new FriendsProgram($SolanaManager) commit('updateIncomingRequest', { ...friendRequest, pending: true }) @@ -456,13 +435,13 @@ export default { const computedFriendAccountKey = await friendsProgram.computeFriendAccountKey( new PublicKey(account.from), - userAccount.publicKey, + payerAccount.publicKey, ) const transactionId = await friendsProgram.denyFriendRequest( computedFriendAccountKey, new PublicKey(account.from), - userAccount, + payerAccount, ) if (transactionId) { @@ -490,12 +469,6 @@ export default { throw new Error(AccountsError.PAYER_NOT_PRESENT) } - const userAccount = await $SolanaManager.getUserAccount() - - if (!userAccount) { - throw new Error(AccountsError.USER_DERIVATION_FAILED) - } - const friendsProgram: FriendsProgram = new FriendsProgram($SolanaManager) commit('updateOutgoingRequest', { ...friendRequest, pending: true }) @@ -504,13 +477,13 @@ export default { const computedFriendAccountMirroredKey = await friendsProgram.computeFriendAccountKey( - userAccount.publicKey, + payerAccount.publicKey, new PublicKey(account.to), ) const transactionId = await friendsProgram.removeFriendRequest( computedFriendAccountMirroredKey, - userAccount, + payerAccount, new PublicKey(account.to), ) @@ -539,19 +512,13 @@ export default { throw new Error(AccountsError.PAYER_NOT_PRESENT) } - const userAccount = await $SolanaManager.getUserAccount() - - if (!userAccount) { - throw new Error(AccountsError.USER_DERIVATION_FAILED) - } - const friendsProgram: FriendsProgram = new FriendsProgram($SolanaManager) const { account } = friend const transactionId = await friendsProgram.removeFriend( account, - userAccount, + payerAccount, ) if (transactionId) { @@ -568,7 +535,7 @@ export default { */ function friendAccountToIncomingRequest( friendAccount: FriendAccount, - userInfo: RawUser | null, + userInfo: UserInfo | null, ): IncomingRequest { return { requestId: friendAccount.accountId, @@ -587,7 +554,7 @@ function friendAccountToIncomingRequest( */ function friendAccountToOutgoingRequest( friendAccount: FriendAccount, - userInfo: RawUser | null, + userInfo: UserInfo | null, ): OutgoingRequest { return { requestId: friendAccount.accountId, diff --git a/types/ui/friends.d.ts b/types/ui/friends.d.ts index ef4b518042..683603faf4 100644 --- a/types/ui/friends.d.ts +++ b/types/ui/friends.d.ts @@ -1,4 +1,5 @@ import { FriendAccount } from '~/libraries/Solana/FriendsProgram/FriendsProgram.types' +import { UserInfo } from '~/libraries/Solana/UsersProgram/UsersProgram' import { RawUser, User } from '~/types/ui/user' export interface EncryptedFriend extends User { @@ -9,7 +10,7 @@ export interface FriendRequest { requestId: string account: FriendAccount pending: boolean - userInfo: RawUser | null + userInfo: UserInfo | null } export interface IncomingRequest extends FriendRequest {