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

node: Updated governor token list update script #3588

Merged
merged 2 commits into from
Dec 13, 2023
Merged
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
3 changes: 2 additions & 1 deletion node/hack/governor/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
lib
node_modules
node_modules
changes.txt
89 changes: 88 additions & 1 deletion node/hack/governor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { Connection, JsonRpcProvider } from "@mysten/sui.js";
import { arrayify, zeroPad } from "ethers/lib/utils";

const MinNotional = 0;
// Price change tolerance in %. Fallback to 30%
const PriceDeltaTolerance = process.env.PRICE_TOLERANCE ? Math.min(100, Math.max(0, parseInt(process.env.PRICE_TOLERANCE))) : 30;

const axios = require("axios");
const fs = require("fs");
Expand Down Expand Up @@ -48,6 +50,21 @@ if (fs.existsSync(IncludeFileName)) {
},
*/

// Get the existing token list to check for any extreme price changes and removed tokens
var existingTokenPrices = {};
var existingTokenKeys: string[] = [];
var newTokenKeys = {};

fs.readFile("../../pkg/governor/generated_mainnet_tokens.go", "utf8", function(_, doc) {
var matches = doc.matchAll(/{chain: (?<chain>[0-9]+).+addr: "(?<addr>[0-9a-fA-F]+)".*symbol: "(?<symbol>.*)", coin.*price: (?<price>.*)}.*\n/g);
djb15 marked this conversation as resolved.
Show resolved Hide resolved
for(let result of matches) {
let {chain, addr, symbol, price} = result.groups;
if (!existingTokenPrices[chain]) existingTokenPrices[chain] = {};
existingTokenPrices[chain][addr] = parseFloat(price);
existingTokenKeys.push(chain + "-" + addr + "-" + symbol);
}
});

axios
.get(
"https://europe-west3-wormhole-message-db-mainnet.cloudfunctions.net/tvl"
Expand All @@ -73,6 +90,11 @@ axios
content += "func generatedMainnetTokenList() []tokenConfigEntry {\n";
content += "\treturn []tokenConfigEntry {\n";

var significantPriceChanges = [];
var addedTokens = [];
var removedTokens = [];
var newTokensCount = 0;

for (let chain in res.data.AllTime) {
for (let addr in res.data.AllTime[chain]) {
if (addr !== "*") {
Expand Down Expand Up @@ -141,6 +163,39 @@ axios
}
}

// This is a new token
if (!existingTokenPrices[chain][wormholeAddr]) {
addedTokens.push(chain + "-" + wormholeAddr + "-" + data.Symbol);
}
// This is an existing token
else {
var previousPrice = existingTokenPrices[chain][wormholeAddr];

// Price has decreased by > tolerance
if (data.TokenPrice < previousPrice - (previousPrice * (PriceDeltaTolerance / 100))){
significantPriceChanges.push({
token: chain + "-" + wormholeAddr + "-" + data.Symbol,
previousPrice: previousPrice,
newPrice: data.TokenPrice,
percentageChange: "-" + (100 - (data.TokenPrice / previousPrice) * 100).toFixed(1).toString()
});
}

// We can also check for tokens that have increased in price, but this actually makes the governor
// limits more aggressive, so is safer from a security point of view. Uncomment the below to also
// be notified of tokens that have significantly increased in value

// Price has increased by > tolerance
// if (data.TokenPrice > previousPrice * ((100 + PriceDeltaTolerance) / 100)) {
// significantPriceChanges.push({
// token: chain + "-" + wormholeAddr + "-" + data.Symbol,
// previousPrice: previousPrice,
// newPrice: data.TokenPrice,
// percentageChange: "+" + (((data.TokenPrice / previousPrice) * 100) - 100).toFixed(1).toString()
// });
// }
}

content +=
"\t{ chain: " +
chain +
Expand All @@ -160,12 +215,44 @@ axios
notional +
"\n";

//console.log("chain: " + chain + ", addr: " + data.Address + ", symbol: " + data.Symbol + ", notional: " + notional + ", price: " + data.TokenPrice + ", amount: " + data.Amount)
newTokenKeys[chain + "-" + wormholeAddr + "-" + data.Symbol] = true;
newTokensCount += 1;
}
}
}
}

for (var token of existingTokenKeys) {
// A token has been removed from the token list
if (!newTokenKeys[token]) {
removedTokens.push(token);
}
}

// Sanity check to make sure the script is doing what we think it is
if (existingTokenKeys.length + addedTokens.length - removedTokens.length != newTokensCount) {
console.error(`Num existing tokens (${existingTokenKeys.length}) + Added tokens (${addedTokens.length}) - Removed tokens (${removedTokens.length}) != Num new tokens (${newTokensCount})`);
process.exit(1);
}

var changedContent = "```\nTokens before = " + existingTokenKeys.length;
changedContent += "\nTokens after = " + newTokensCount;
changedContent += "\n\nTokens added = " + addedTokens.length + ":\n<WH_chain_id>-<WH_token_addr>-<token_symbol>\n\n";
changedContent += JSON.stringify(addedTokens, null, 1);
changedContent += "\n\nTokens removed = " + removedTokens.length + ":\n<WH_chain_id>-<WH_token_addr>-<token_symbol>\n\n";
changedContent += JSON.stringify(removedTokens, null, 1);
changedContent += "\n\nTokens with significant price drops (>" + PriceDeltaTolerance + "%) = " + significantPriceChanges.length + ":\n\n"
changedContent += JSON.stringify(significantPriceChanges, null, 1);
djb15 marked this conversation as resolved.
Show resolved Hide resolved
changedContent += "\n```";

await fs.writeFileSync(
"./changes.txt",
changedContent,
{
flag: "w+",
}
);
djb15 marked this conversation as resolved.
Show resolved Hide resolved

content += "\t}\n";
content += "}\n";

Expand Down
7 changes: 4 additions & 3 deletions node/pkg/governor/mainnet_tokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import (
func TestTokenListSize(t *testing.T) {
tokenConfigEntries := tokenList()

/* Assuming that governed tokens will need to be updated every time
we regenerate it */
assert.Equal(t, 1034, len(tokenConfigEntries))
// We should have a sensible number of tokens
// These numbers shouldn't have to change frequently
assert.Greater(t, len(tokenConfigEntries), 1000)
assert.Less(t, len(tokenConfigEntries), 2000)
}

func TestTokenListAddressSize(t *testing.T) {
Expand Down
Loading