Skip to content

Commit

Permalink
Merge pull request #48 from Muzikie/37-solana-program-interaction-for…
Browse files Browse the repository at this point in the history
…-create-new-campaign-1

Solana program interaction for create new campaign
  • Loading branch information
reyraa authored Oct 8, 2024
2 parents 2c037d9 + 3937736 commit d34ba7a
Show file tree
Hide file tree
Showing 15 changed files with 1,414 additions and 165 deletions.
20 changes: 0 additions & 20 deletions .env.example

This file was deleted.

6 changes: 0 additions & 6 deletions config/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ module.exports = ({ env }) => ({
'users-permissions': {
config: {
jwtSecret: env('ADMIN_JWT_SECRET'),
providers: {
google: {
clientId: env('GOOGLE_CLIENT_ID'),
redirectUri: 'muzikie://auth/callback',
},
},
},
},
upload: {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"lint": "eslint"
},
"dependencies": {
"@coral-xyz/anchor": "^0.30.1",
"@solana/web3.js": "^1.95.3",
"@strapi/plugin-cloud": "4.25.1",
"@strapi/plugin-i18n": "4.25.1",
Expand Down
49 changes: 45 additions & 4 deletions src/api/contribution-tier/controllers/contribution-tier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
* contribution-tier controller
*/

import { factories } from '@strapi/strapi'
import { factories } from '@strapi/strapi';
import { BN } from '@coral-xyz/anchor';
import { Keypair, PublicKey } from '@solana/web3.js';

import { decryptPrivateKey } from '../../../utils/crypto';
import { getProgramDetails, getProjectPDA } from '../../../utils/network';
import { EncryptedSecretKeyMeta } from '../../../utils/types';

export default factories.createCoreController('api::contribution-tier.contribution-tier', ({ strapi }) => ({
// POST
async create(ctx) {
const { user } = ctx.state;
let entityId: string = '';

try {
const now = new Date();
Expand All @@ -18,12 +25,46 @@ export default factories.createCoreController('api::contribution-tier.contributi

// Proceed with creating the the project
const result = await super.create(ctx);
entityId = result.data.id;

const wallet = await strapi.entityService.findMany(
'api::wallet.wallet',
{
filters: {
users_permissions_user: user.id,
},
}
);

if (wallet.length === 1) {
const { iv, encryptedData } = wallet[0].encrypted_private_key as unknown as EncryptedSecretKeyMeta;
const privateKey = decryptPrivateKey(encryptedData, iv);
const keyPair = Keypair.fromSecretKey(privateKey);

const program = getProgramDetails(keyPair);
const projectPDA = getProjectPDA(ctx.request.body.data.project, program);

const projectState = await program.account.projectState.fetch(projectPDA);
console.log({projectState})

// TODO: Call the Smart Contract method here to register the project on the blockchain
// and if not created, revert the centralized project creation.
await program.methods.addContributionTier(
new BN(result.data.id),
new BN(result.data.attributes.amount),
)
.accounts({
project: projectPDA,
owner: new PublicKey(wallet[0].public_key),
})
.signers([keyPair])
.rpc();

return result;
return result;
} else {
// @todo ridi
throw new Error('Could not find associated wallet');
}
} catch (err) {
await strapi.entityService.delete('api::contribution-tier.contribution-tier', entityId);
ctx.throw(500, err);
}
}
Expand Down
45 changes: 45 additions & 0 deletions src/api/contribution/controllers/contribution.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { factories } from '@strapi/strapi';
import { BN } from '@coral-xyz/anchor';
import { Keypair, PublicKey } from '@solana/web3.js';

import { decryptPrivateKey } from '../../../utils/crypto';
import { getProgramDetails, getProjectPDA } from '../../../utils/network';
import { EncryptedSecretKeyMeta } from '../../../utils/types';

export default factories.createCoreController('api::contribution.contribution', ({ strapi }) => ({
async create(ctx) {
const { user } = ctx.state;
const { contribution_tier } = ctx.request.body;
let contributionId;

try {
// Find the contribution tier and associated project
Expand Down Expand Up @@ -36,6 +43,8 @@ export default factories.createCoreController('api::contribution.contribution',
},
});

contributionId = contribution.id;

// Update the project's current_funding
await strapi.entityService.update('api::project.project', project.id, {
data: {
Expand All @@ -46,9 +55,45 @@ export default factories.createCoreController('api::contribution.contribution',
// Return the created contribution
const sanitizedEntity = await this.sanitizeOutput(contribution, ctx);

const wallet = await strapi.entityService.findMany(
'api::wallet.wallet',
{
filters: {
users_permissions_user: user.id,
},
},
);

if (wallet.length === 1) {
const { iv, encryptedData } = wallet[0]
.encrypted_private_key as unknown as EncryptedSecretKeyMeta;
const privateKey = decryptPrivateKey(encryptedData, iv);
const keyPair = Keypair.fromSecretKey(privateKey);
const program = getProgramDetails(keyPair);
const projectPDA = getProjectPDA(String(project.id), program);

const networkResult = await program.methods
.contribute(
new BN(tier.id),
new BN(tier.amount),
)
.accounts({
contributor: new PublicKey(wallet[0].public_key),
escrow: new PublicKey(process.env.ESCROW_PUBLIC_KEY),
project: projectPDA,
})
.signers([keyPair])
.rpc();
} else {
throw new Error('Could not find associated wallet');
}
// before returning the value, make sure to update the Solana project too
return this.transformResponse(sanitizedEntity);
} catch (err) {
await strapi.entityService.delete(
'api::contribution.contribution',
contributionId,
);
ctx.throw(500, err);
}
},
Expand Down
21 changes: 10 additions & 11 deletions src/api/profile/services/profile.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
/**
* profile service
*/

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

import {encryptPrivateKey} from '../../../utils/crypto';
import {SupportedBlockchains} from '../../../utils/types';
import { encryptPrivateKey, decryptPrivateKey } from '../../../utils/crypto'; // Import updated

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: {
Expand All @@ -25,11 +22,13 @@ export default factories.createCoreService('api::profile.profile', {
publishedAt: now,
},
});

// Create a wallet for the new user
const wallet = Keypair.generate();
const iv = crypto.randomBytes(16);
const privateKey = wallet.secretKey.toString();
const privateKey = wallet.secretKey;
console.log('privateKey on generation', privateKey);
console.log('address on generation', wallet.publicKey);
await strapi.entityService.create('api::wallet.wallet', {
data: {
public_key: wallet.publicKey.toString(),
Expand All @@ -42,7 +41,7 @@ export default factories.createCoreService('api::profile.profile', {
publishedAt: now,
},
});

strapi.log.info(`Profile and wallet created for user ${userId}`);
} catch (error) {
strapi.log.error('Error during profile or wallet creation:', error);
Expand Down
Loading

0 comments on commit d34ba7a

Please sign in to comment.