Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api-server/classes/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import properties from "../properties.js";
// Controllers
import SecurityController from "../controllers/SecurityController";
import PythController from "../controllers/PythController";
import StakeController from "../controllers/StakeController";

// Start Import Controllers

Expand Down Expand Up @@ -97,6 +98,7 @@ class Server {
const router = express.Router();
SecurityController.init(router);
PythController.init(router);
StakeController.init(router);
// End Init Controllers

this.app.use("/", router);
Expand Down
144 changes: 144 additions & 0 deletions api-server/controllers/StakeController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/**
* Get SOL price from Pyth oracle
*/
import Properties from "../properties";
import * as anchor from "@project-serum/anchor";
const serumCmn = require("@project-serum/common");
const spl = require("@solana/spl-token");

let provider = null;
let program = null;
let walletKey = null;

// These are in devnet only
const tokenAccount = new anchor.web3.PublicKey("66toRwKMVFGBLrwWzc4yTBfZj1SWvENxSBqxD1Hq3iZy");
const REWARD_TOKEN_MINT = new anchor.web3.PublicKey("4m3TqQy4Vp4VLp9Bq4FJyWsfxRsU5nNutF2rRQf9QxW5");

// Extract the values from the properties file
const {
BASE_API_URL,
} = Properties;

const StakeController = {
/**
* Init routes
*/
init: router => {
// Extract provider from the env variable
// ANCHOR_PROVIDER_URL
provider = anchor.Provider.env();

// Configure the client to use the local cluster.
anchor.setProvider(provider);

// Connect to the reward staking program
program = anchor.workspace.RewardTokenStaking;

walletKey = new anchor.web3.PublicKey(program.provider.wallet.publicKey);

// Register router
router.post(BASE_API_URL + "/stake", StakeController.doStake);
router.post(BASE_API_URL + "/unstake", StakeController.doUnstake);
},

/**
* Perform the reward token staking
*
* @param {Object} req Http Request object
* @param {Object} res Http Response object
*/
doStake: async (req, res) => {
try {
// Create data account
const dataAccount = anchor.web3.Keypair.generate();

// Create a key pair for the vault
const vault = anchor.web3.Keypair.generate();

// Get the check signer and nonce
const [_checkSigner, _nonce] = await anchor.web3.PublicKey.findProgramAddress(
[dataAccount.publicKey.toBuffer()],
program.programId
);
const checkSigner = _checkSigner;
const nonce = _nonce;

// Convert the amount to the correct value
const stakeAmount = req.body.amount * 1000000000;

// Perform the stake request
await program.rpc.stake(new anchor.BN(stakeAmount), "Zero Interest", nonce, {
accounts: {
dataAccount: dataAccount.publicKey,
vault: vault.publicKey,
checkSigner,
from: tokenAccount,
owner: walletKey,
tokenProgram: spl.TOKEN_PROGRAM_ID,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
},
signers: [dataAccount, vault],
instructions: [
await program.account.stake.createInstruction(dataAccount, 300),
...(await serumCmn.createTokenAccountInstrs(
program.provider,
vault.publicKey,
REWARD_TOKEN_MINT,
checkSigner
)),
],
});

// Return the vault and data account public keys
res.json({
vault: vault.publicKey.toBase58(),
dataAccount: dataAccount.publicKey.toBase58(),
});

} catch (error) {
// Log the error if it happens
console.error(error);

// Return status 500
res.status(500);
res.json("Staking failed. " + error.toString());
}
},

doUnstake: async (req, res) => {
try {
// Extract the public keys of both the vault and the data account
const { vault, dataAccount } = req.body;
const dataAccountPubKey = await new anchor.web3.PublicKey(dataAccount);
const vaultPubKey = await new anchor.web3.PublicKey(vault);

// Get the check signer
const [_checkSigner] = await anchor.web3.PublicKey.findProgramAddress(
[dataAccountPubKey.toBuffer()],
program.programId
);
const checkSigner = _checkSigner;

// Perform the unstake function in the blockchain
await program.rpc.unstake({
accounts: {
dataAccount: dataAccountPubKey,
vault: vaultPubKey,
checkSigner,
from: tokenAccount,
owner: walletKey,
tokenProgram: spl.TOKEN_PROGRAM_ID,
},
});

res.json("Unstaking success");
} catch (error) {
// Log the error if it happens
console.error(error)
res.status(500);
res.json("Unstaking failed. " + error.toString());
}
}
};

export default StakeController;
2 changes: 2 additions & 0 deletions api-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"dependencies": {
"@babel/core": "^7.0.0",
"@project-serum/anchor": "^0.10.0",
"@project-serum/common": "^0.0.1-beta.3",
"@solana/spl-token": "^0.1.6",
"@solana/web3.js": "^1.20.0",
"@types/node-fetch": "^2.5.7",
"body-parser": "^1.17.2",
Expand Down
Loading