-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from alpaca-finance/chore/pyth-paradeen-feed-s…
…cript [main][chore] pyth paradeen feed script
- Loading branch information
Showing
5 changed files
with
166 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { HardhatRuntimeEnvironment } from "hardhat/types"; | ||
import { DeployFunction } from "hardhat-deploy/types"; | ||
import { ethers } from "hardhat"; | ||
import { getConfig } from "../utils/config"; | ||
import { BigNumber } from "ethers"; | ||
import { | ||
AP__factory, | ||
ERC20__factory, | ||
Paradeen__factory, | ||
} from "../../typechain"; | ||
import * as readlineSync from "readline-sync"; | ||
import { getCoinGeckoPriceUSD } from "../utils/price"; | ||
import { formatEther } from "ethers/lib/utils"; | ||
|
||
interface FeedParadeenParams { | ||
weekTimestamp: BigNumber; | ||
amount: BigNumber; | ||
} | ||
|
||
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { | ||
const config = getConfig(); | ||
const signer = (await ethers.getSigners())[0]; | ||
const pythExponent = BigNumber.from(10).pow(6); | ||
|
||
// contracts | ||
const ap = AP__factory.connect(config.TradeMining.AP, ethers.provider); | ||
const pyth = ERC20__factory.connect(config.TradeMining.rewardToken, signer); | ||
const paradeen = Paradeen__factory.connect( | ||
config.TradeMining.pythParadeen, | ||
signer | ||
); | ||
|
||
// constants | ||
const E18 = BigNumber.from(10).pow(18); | ||
const WEEK = BigNumber.from(604800); | ||
const MAX_BPS = BigNumber.from(10000); | ||
|
||
// configs | ||
const tradingFeeBps = 9; | ||
const weeklyFeeThreshold = BigNumber.from(20000).mul(E18); | ||
const endTimestamp = 1716422400; // May 23, 2024 | ||
|
||
console.log(`> Prepare data...`); | ||
|
||
const currentBlock = await ethers.provider.getBlock("latest"); | ||
const weekCursor = BigNumber.from(currentBlock.timestamp).div(WEEK).mul(WEEK); | ||
|
||
const weeklyTradingVolume = await ap.weeklyTotalSupply(weekCursor); | ||
const tradingFeeCollected = weeklyTradingVolume | ||
.mul(tradingFeeBps) | ||
.mul(2) // account closing volume assure | ||
.div(MAX_BPS); | ||
const pythPrice = await getCoinGeckoPriceUSD("pyth-network"); | ||
|
||
console.log(`> Weekly trading volume: ${formatEther(weeklyTradingVolume)}`); | ||
console.log(`> Trading fee collected: ${formatEther(tradingFeeCollected)}`); | ||
console.log(`> Pyth price: ${formatEther(pythPrice)}\n`); | ||
|
||
let amountToFeed: BigNumber; | ||
|
||
if (tradingFeeCollected.lt(weeklyFeeThreshold)) { | ||
console.log( | ||
`> Trading fee collected is < ${formatEther(weeklyFeeThreshold)} USD` | ||
); | ||
amountToFeed = tradingFeeCollected.mul(E18).div(pythPrice); | ||
} else { | ||
console.log( | ||
`> Trading fee collected is > ${formatEther(weeklyFeeThreshold)} USD` | ||
); | ||
amountToFeed = weeklyFeeThreshold.mul(E18).div(pythPrice); | ||
} | ||
|
||
console.log(`> Amount to feed: ${formatEther(amountToFeed)} Pyth`); | ||
|
||
const PARAMS_INPUT: Array<FeedParadeenParams> = [ | ||
{ | ||
weekTimestamp: weekCursor, | ||
amount: amountToFeed.mul(pythExponent).div(E18), | ||
}, | ||
]; | ||
|
||
// Check feed timestamp | ||
const weeklyReward = await paradeen.tokensPerWeek(weekCursor); | ||
if (weeklyReward.gt(0)) { | ||
console.log("===================================="); | ||
console.log( | ||
`> Weekly reward for ${weekCursor}: ${formatEther( | ||
weeklyReward.mul(E18).div(pythExponent) | ||
)} Pyth` | ||
); | ||
console.log(`> Already fed for this week`); | ||
const goNext = readlineSync.question( | ||
"Confirm to re-feed (increase)? (y/n): " | ||
); | ||
switch (goNext.toLowerCase()) { | ||
case "y": | ||
break; | ||
case "n": | ||
console.log("Aborting"); | ||
return; | ||
default: | ||
console.log("Invalid input"); | ||
return; | ||
} | ||
} | ||
|
||
if (weekCursor.gt(endTimestamp)) { | ||
console.log("> The campaign has ended, no need to feed"); | ||
return; | ||
} | ||
|
||
// Ask for confirmation | ||
console.table(PARAMS_INPUT); | ||
const confirm = readlineSync.question("Confirm? (y/n): "); | ||
switch (confirm.toLowerCase()) { | ||
case "y": | ||
break; | ||
case "n": | ||
console.log("Aborting"); | ||
return; | ||
default: | ||
console.log("Invalid input"); | ||
return; | ||
} | ||
|
||
const timestamps = PARAMS_INPUT.map((p) => | ||
p.weekTimestamp.div(WEEK).mul(WEEK) | ||
); | ||
const amounts = PARAMS_INPUT.map((p) => p.amount); | ||
|
||
console.log("> Approving Pyth to Paradeen..."); | ||
const approvedTx = await pyth.approve(paradeen.address, amountToFeed); | ||
console.log(`> ⛓ Tx submitted: ${approvedTx.hash}`); | ||
|
||
console.log("> Feeding rewards to Paradeen"); | ||
const tx = await paradeen.feed(timestamps, amounts); | ||
console.log(`> ⛓ Tx submitted: ${tx.hash}`); | ||
console.log(`> Waiting tx to be mined...`); | ||
await tx.wait(); | ||
console.log(`> Tx mined!`); | ||
}; | ||
|
||
export default func; | ||
func.tags = ["FeedParadeenPyth"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import axios from "axios"; | ||
import { BigNumber } from "ethers"; | ||
import { parseEther } from "ethers/lib/utils"; | ||
|
||
export async function getCoinGeckoPriceUSD( | ||
assetId: string | ||
): Promise<BigNumber> { | ||
let tokenPrice = BigNumber.from(0); | ||
try { | ||
const response = await axios.get( | ||
`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=${assetId}` | ||
); | ||
tokenPrice = parseEther(response.data[0]["current_price"].toString()); | ||
} catch (error) { | ||
throw new Error(`Error fetching price for ${assetId}: ${error}`); | ||
} | ||
|
||
return tokenPrice; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters