Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Prosper #12950

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
85 changes: 85 additions & 0 deletions projects/prosper/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const axios = require("axios");

// ------------------------------
// CONFIG
// ------------------------------
const RECEIPT_TOKEN = "0xb4A05f1dc74876f9C59368569A9454cF09cBea2E";
const ORIGINAL_TOKEN = "0xEd8c8Aa8299C10f067496BB66f8cC7Fb338A3405";

// USDC on BSC (no 'bsc:' prefix; the system adds it automatically)
const USDC_ADDRESS = "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d";

// Hashrate endpoints
const HASHRATE_API_URL_1 =
"https://www.antpool.com/auth/v3/observer/api/hash/query?accessKey=kDe236rMHQwZbz1f5qma&coinType=BTC&observerUserId=ANTPOOL22024";
const HASHRATE_API_URL_2 =
"https://www.antpool.com/auth/v3/observer/api/hash/query?accessKey=YwP7KdLB1pjaXR8lB2iw&coinType=BTC&observerUserId=antpool42024";

// Per comparables research as of 12 Dec 2024: $119.8M per EH/s
const VALUATION_MULTIPLE = 119800000;

// ------------------------------
// 1) tvl => hashrate + staking
// ------------------------------
async function tvlAndStaking(api) {
// PART A: Hashrate -> USD
try {
const [res1, res2] = await Promise.all([
axios.get(HASHRATE_API_URL_1),
axios.get(HASHRATE_API_URL_2),
]);

// Convert PH/s => EH/s
const hashrate1 = (parseFloat(res1?.data?.data?.hsLast1D) || 0) / 1000;
const hashrate2 = (parseFloat(res2?.data?.data?.hsLast1D) || 0) / 1000;
const totalHashrate = hashrate1 + hashrate2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be calculated using on chain methods opposed to a proprietary api?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Antpool API would be the most accurate source of how much hashrate the protocol currently has live, as Antpool is the mining pool provider / operator.

The part that we look into making on-chain is the valuation multiple—we'll check to see if any of the oracles provide the relevant data.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @waynebruce0x , we've looked further into the valuation multiple calculation. We would propose the below. Let us know your thoughts before we proceed with implementation:

  1. Protocol's hashrate - source from Antpool API. This is the most accurate source of how much hashrate the protocol currently has live, as Antpool is the mining pool provider / operator. This data does not appear to be available via Chainlink or similar.

  2. Valuation multiple - source from a public Google Sheet via Google Sheets API. On the publicly accessible sheet, list of publicly listed mining companies is compiled, together with enterprise value data and hashrate data from reputable sources (https://sheetsfinance.com/ for enterprise value and https://data.hashrateindex.com/stocks API). The compiled data is used to calculate the valuation multiple, which can be then returned finally using the Google Sheets API. Unfortunately, this data does not appear to be available on Chainlink or similar either.

Let us know what you think of this approach!


const rwaUsdValue = totalHashrate * VALUATION_MULTIPLE;
// Represent as USDC
const bigValue = Math.round(rwaUsdValue * 1e18);
api.add(USDC_ADDRESS, bigValue);
} catch (err) {
console.error("Error fetching hashrate:", err);
}

// PART B: Staking
// => treat the total supply of the receipt token as the "original token" balance
const totalSupply = await api.call({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic should only be in stakingOnly()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We included staking again here as well so the total TVL would be the hashrate + staking value. We actually had it initially as just hashrate and then just staking, but then the total TVL given by the testing function would only include the hashrate TVL and exclude the staking portion.

Would you suggest to use a different function name / category for the hashrate portion?

abi: "erc20:totalSupply",
target: RECEIPT_TOKEN,
});

// Add it as the original token
api.add(ORIGINAL_TOKEN, totalSupply);

// Return combined balances (hashrate + staking)
return api.getBalances();
}

// ------------------------------
// 2) Only staking
// ------------------------------
async function stakingOnly(api) {
// Just do the staking logic
const totalSupply = await api.call({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use the staking contact balance instead of totalsupply?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use the totalSupply of the "receipt" token (rePROS) here as it should be the most accurate reflection of how many tokens are currently staked. The staking contract balance of PROS may be slightly higher than how many are staked because we have an unbonding period of 72h. That is, once a user unstakes their PROS, that balance would still be in the contract until after the unbonding period and after they claim their tokens—however, the rePROS balance would already have decreased.

abi: "erc20:totalSupply",
target: RECEIPT_TOKEN,
});

// Add as the original token
api.add(ORIGINAL_TOKEN, totalSupply);

return api.getBalances();
}

// ------------------------------
// Module Exports
// ------------------------------
module.exports = {
methodology:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this adapter is exporting a USDC amount, misrepresentedTokens: true should be added here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will update!

"TVL combines the estimated value (represented as USDC) of tokenized RWA hashrate by multiplying live hashrate value (in EH/s) × valuation multiple ($119.8M per EH/s) + staked PROS tokens",
bsc: {
tvl: tvlAndStaking, // hashrate + staking
staking: stakingOnly // only staking
},
};
Loading