Skip to content

Commit

Permalink
Merge pull request #44 from Muzikie/43-add-support-for-wallet
Browse files Browse the repository at this point in the history
Add support for wallet
  • Loading branch information
reyraa authored Sep 30, 2024
2 parents 24385e9 + 179c24d commit e2060e3
Show file tree
Hide file tree
Showing 13 changed files with 477 additions and 75 deletions.
6 changes: 0 additions & 6 deletions config/middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,4 @@ export default [
'strapi::session',
'strapi::favicon',
'strapi::public',
{
resolve: './src/middlewares/custom/signup',
config: {
enabled: true,
},
},
];
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
"lint": "eslint"
},
"dependencies": {
"@solana/web3.js": "^1.95.3",
"@strapi/plugin-cloud": "4.25.1",
"@strapi/plugin-i18n": "4.25.1",
"@strapi/plugin-users-permissions": "^4.25.6",
"@strapi/strapi": "4.25.1",
"better-sqlite3": "8.6.0",
"crypto": "^1.0.1",
"pg": "^8.12.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
Expand Down
6 changes: 0 additions & 6 deletions src/api/profile/content-types/profile/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@
"relation": "oneToOne",
"target": "plugin::users-permissions.user"
},
"wallet": {
"type": "relation",
"relation": "oneToOne",
"target": "api::wallet.wallet",
"mappedBy": "profile"
},
"points": {
"type": "integer",
"required": true,
Expand Down
47 changes: 46 additions & 1 deletion src/api/profile/services/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,50 @@
*/

import { factories } from '@strapi/strapi';
import {Keypair} from '@solana/web3.js';
import crypto from 'crypto';

export default factories.createCoreService('api::profile.profile');
import {encryptPrivateKey} from '../../../utils/crypto';
import {SupportedBlockchains} from '../../../utils/types';

export default factories.createCoreService('api::profile.profile', {
addProfileAndWallet: async (userId: string) => {
try {
const now = new Date().getTime();

// Create a profile for the new user
await strapi.entityService.create('api::profile.profile', {
data: {
first_name: '',
las_name: '',
points: 0,
users_permissions_user: userId,
createdAt: now,
publishedAt: now,
},
});

// Create a wallet for the new user
const wallet = Keypair.generate();
const iv = crypto.randomBytes(16);
const privateKey = wallet.secretKey.toString();
await strapi.entityService.create('api::wallet.wallet', {
data: {
public_key: wallet.publicKey.toString(),
encrypted_private_key: encryptPrivateKey(privateKey, iv),
address: wallet.publicKey.toBase58(),
blockchain: SupportedBlockchains.Solana,
encryption_metadata: {},
users_permissions_user: userId,
createdAt: now,
publishedAt: now,
},
});

strapi.log.info(`Profile and wallet created for user ${userId}`);
} catch (error) {
strapi.log.error('Error during profile or wallet creation:', error);
// @todo we should delete the user and inform the client about the error
}
},
});
26 changes: 19 additions & 7 deletions src/api/wallet/content-types/wallet/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,35 @@
},
"pluginOptions": {},
"attributes": {
"public_key": {
"type": "string",
"required": true,
"unique": true
},
"encrypted_private_key": {
"type": "json",
"required": true
},
"address": {
"type": "string",
"required": true
},
"balance": {
"type": "biginteger",
"default": "0",
"encryption_metadata": {
"type": "json",
"required": true
},
"seed": {
"type": "string",
"blockchain": {
"type": "enumeration",
"enum": [
"Solana",
"Klayr"
],
"required": true
},
"profile": {
"users_permissions_user": {
"type": "relation",
"relation": "oneToOne",
"target": "api::profile.profile",
"target": "plugin::users-permissions.user",
"inversedBy": "wallet"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@
"relation": "oneToMany",
"target": "api::contribution.contribution",
"mappedBy": "users_permissions_user"
},
"wallet": {
"type": "relation",
"relation": "oneToOne",
"target": "api::wallet.wallet",
"mappedBy": "users_permissions_user"
}
}
}
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,11 @@ export default {
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*/
bootstrap(/*{ strapi }*/) {},
bootstrap({ strapi }) {
strapi.db.lifecycles.subscribe((event) => {
if (event.action === 'afterCreate' && event.model.collectionName === 'up_users') {
strapi.service('api::profile.profile').addProfileAndWallet(event.result.id);
}
});
},
};
File renamed without changes.
35 changes: 0 additions & 35 deletions src/middlewares/custom/signup.ts

This file was deleted.

18 changes: 18 additions & 0 deletions src/utils/crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import crypto from 'crypto';

const algorithm = 'aes-256-cbc';
const PVK_ENCRYPTION_SALT = process.env.PVK_ENCRYPTION_SALT;
const pvkEncryptionSalt = Buffer.from(PVK_ENCRYPTION_SALT, 'hex');

export const encryptPrivateKey = (privateKey: string, iv: Buffer) => {
if (!PVK_ENCRYPTION_SALT) {
throw new Error('Error: The env variable PVK_ENCRYPTION_SALT is missing');
}

const cipher = crypto.createCipheriv(algorithm, pvkEncryptionSalt, iv);
const encrypted = Buffer.concat([cipher.update(privateKey), cipher.final()]);
return {
iv: iv.toString('hex'),
encryptedData: encrypted.toString('hex'),
};
};
3 changes: 3 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum SupportedBlockchains {
Solana = 'Solana',
}
22 changes: 11 additions & 11 deletions types/generated/contentTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,11 @@ export interface PluginUsersPermissionsUser extends Schema.CollectionType {
'oneToMany',
'api::contribution.contribution'
>;
wallet: Attribute.Relation<
'plugin::users-permissions.user',
'oneToOne',
'api::wallet.wallet'
>;
createdAt: Attribute.DateTime;
updatedAt: Attribute.DateTime;
createdBy: Attribute.Relation<
Expand Down Expand Up @@ -1080,11 +1085,6 @@ export interface ApiProfileProfile extends Schema.CollectionType {
'oneToOne',
'plugin::users-permissions.user'
>;
wallet: Attribute.Relation<
'api::profile.profile',
'oneToOne',
'api::wallet.wallet'
>;
points: Attribute.Integer &
Attribute.Required &
Attribute.SetMinMax<
Expand Down Expand Up @@ -1414,15 +1414,15 @@ export interface ApiWalletWallet extends Schema.CollectionType {
draftAndPublish: true;
};
attributes: {
public_key: Attribute.String & Attribute.Required & Attribute.Unique;
encrypted_private_key: Attribute.JSON & Attribute.Required;
address: Attribute.String & Attribute.Required;
balance: Attribute.BigInteger &
Attribute.Required &
Attribute.DefaultTo<'0'>;
seed: Attribute.String & Attribute.Required;
profile: Attribute.Relation<
encryption_metadata: Attribute.JSON & Attribute.Required;
blockchain: Attribute.Enumeration<['Solana', 'Klayr']> & Attribute.Required;
users_permissions_user: Attribute.Relation<
'api::wallet.wallet',
'oneToOne',
'api::profile.profile'
'plugin::users-permissions.user'
>;
createdAt: Attribute.DateTime;
updatedAt: Attribute.DateTime;
Expand Down
Loading

0 comments on commit e2060e3

Please sign in to comment.