Skip to content

Commit

Permalink
dashboard: ntt total supply on evm vs total locked on sol
Browse files Browse the repository at this point in the history
Signed-off-by: bingyuyap <bingyu.yap.21@gmail.com>
  • Loading branch information
bingyuyap committed Apr 24, 2024
1 parent 207e10a commit d740f83
Show file tree
Hide file tree
Showing 21 changed files with 708 additions and 428 deletions.
4 changes: 4 additions & 0 deletions cloud_functions/scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ gcloud functions --project "$GCP_PROJECT" deploy reobserve-vaas --entry-point ge
gcloud functions --project "$GCP_PROJECT" deploy tvl --entry-point getTVL --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 256MB --region europe-west3 --set-env-vars FIRESTORE_TVL_COLLECTION=$FIRESTORE_TVL_COLLECTION,NETWORK=$NETWORK
gcloud functions --project "$GCP_PROJECT" deploy tvl-history --entry-point getTVLHistory --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 256MB --region europe-west3 --set-env-vars FIRESTORE_TVL_HISTORY_COLLECTION=$FIRESTORE_TVL_HISTORY_COLLECTION,NETWORK=$NETWORK
gcloud functions --project "$GCP_PROJECT" deploy vaas-by-tx-hash --entry-point getVaasByTxHash --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 256MB --region europe-west3 --set-env-vars BIGTABLE_INSTANCE_ID=$BIGTABLE_INSTANCE_ID,BIGTABLE_SIGNED_VAAS_TABLE_ID=$BIGTABLE_SIGNED_VAAS_TABLE_ID,BIGTABLE_VAAS_BY_TX_HASH_TABLE_ID=$BIGTABLE_VAAS_BY_TX_HASH_TABLE_ID,NETWORK=$NETWORK
gcloud functions --project "$GCP_PROJECT" deploy get-ntt-rate-limits --entry-point getNTTRateLimits --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 256MB --region europe-west3 --set-env-vars NETWORK=$NETWORK
gcloud functions --project "$GCP_PROJECT" deploy compute-ntt-rate-limits --entry-point computeNTTRateLimits --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 256MB --region europe-west3 --set-env-vars NETWORK=$NETWORK
gcloud functions --project "$GCP_PROJECT" deploy get-total-supply-and-locked --entry-point getTotalSupplyAndLocked --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 256MB --region europe-west3 --set-env-vars NETWORK=$NETWORK
gcloud functions --project "$GCP_PROJECT" deploy compute-total-supply-and-locked --entry-point computeTotalSupplyAndLocked --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 256MB --region europe-west3 --set-env-vars NETWORK=$NETWORK

#
# Bail out if we are only deploying TESTNET functions
Expand Down
136 changes: 136 additions & 0 deletions cloud_functions/src/computeNTTRateLimits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import {
assertEnvironmentVariable,
NTT_MANAGER_CONTRACT,
NTT_TOKENS,
NTT_TRANSCEIVER_CONTRACT,
NTT_SUPPORTED_CHAINS,
getEvmTokenDecimals,
getSolanaTokenDecimals,
NTTRateLimit,
} from '@wormhole-foundation/wormhole-monitor-common';
import { EvmPlatform, EvmChains } from '@wormhole-foundation/sdk-evm';
import { SolanaPlatform } from '@wormhole-foundation/sdk-solana';
import { EvmNtt } from '@wormhole-foundation/sdk-evm-ntt';
import { SolanaNtt } from '@wormhole-foundation/sdk-solana-ntt';
import { Network, Chain, contracts, rpc, chainToChainId } from '@wormhole-foundation/sdk-base';
import { Storage } from '@google-cloud/storage';

const storage = new Storage();
let bucketName: string = 'wormhole-ntt-cache';
if (assertEnvironmentVariable('NETWORK') === 'Testnet') {
bucketName = 'wormhole-ntt-cache-testnet';
}

const cacheBucket = storage.bucket(bucketName);
const cacheFileName = 'ntt-rate-limits-cache.json';
const cloudStorageCache = cacheBucket.file(cacheFileName);

async function computeNTTRateLimits_(
network: Network,
token: string,
chain: Chain
): Promise<NTTRateLimit> {
let ntt: EvmNtt<Network, EvmChains> | SolanaNtt<Network, 'Solana'>;
let tokenDecimals: number;
const rpcEndpoint = rpc.rpcAddress(network, chain as Chain);
const tokenAddress = NTT_TOKENS[network][token][chain]!;
const managerContract = NTT_MANAGER_CONTRACT[network][token][chain]!;
const transceiverContract = NTT_TRANSCEIVER_CONTRACT[network][token][chain]!;

if (chain === 'Solana') {
const platform = new SolanaPlatform(network);
ntt = new SolanaNtt(network, chain, platform.getRpc(chain), {
coreBridge: contracts.coreBridge(network, chain),
ntt: {
token: tokenAddress,
manager: managerContract,
transceiver: {
wormhole: transceiverContract,
},
},
});
tokenDecimals = await getSolanaTokenDecimals(rpcEndpoint, tokenAddress);
} else {
const evmChain = chain as EvmChains;
const platform = new EvmPlatform(network);
ntt = new EvmNtt(network, evmChain, platform.getRpc(evmChain), {
ntt: {
token: tokenAddress,
manager: managerContract,
transceiver: {
wormhole: transceiverContract,
},
},
});
tokenDecimals = await getEvmTokenDecimals(rpcEndpoint, managerContract);
}

const outboundCapacity = await ntt.getCurrentOutboundCapacity();
const normalizedOutboundCapacity = outboundCapacity / BigInt(10 ** tokenDecimals);

const inboundChains = NTT_SUPPORTED_CHAINS(network, token).filter(
(inboundChain) => inboundChain !== chain
);

let totalInboundCapacity = BigInt(0);
const inboundRateLimits = await Promise.all(
inboundChains.map(async (inboundChain): Promise<NTTRateLimit> => {
const inboundCapacity = await ntt.getCurrentInboundCapacity(inboundChain);
const normalizedInboundCapacity = inboundCapacity / BigInt(10 ** tokenDecimals);
totalInboundCapacity += normalizedInboundCapacity;

return {
tokenName: token,
srcChain: chainToChainId(inboundChain),
destChain: chainToChainId(chain),
amount: normalizedInboundCapacity.toString(),
};
})
);

return {
tokenName: token,
srcChain: chainToChainId(chain),
amount: normalizedOutboundCapacity.toString(),
inboundCapacity: inboundRateLimits,
totalInboundCapacity: totalInboundCapacity.toString(),
};
}

export async function computeNTTRateLimits(req: any, res: any) {
res.set('Access-Control-Allow-Origin', '*');
if (req.method === 'OPTIONS') {
res.set('Access-Control-Allow-Methods', 'GET');
res.set('Access-Control-Allow-Headers', 'Content-Type');
res.set('Access-Control-Max-Age', '3600');
res.sendStatus(204);
return;
}

try {
const network = assertEnvironmentVariable('NETWORK') as Network;
const managerContracts = NTT_MANAGER_CONTRACT[network];

const rateLimits = await Promise.all(
Object.entries(managerContracts).map(async ([token, manager]) => {
const inboundCapacityPromises = Object.entries(manager)
.map(([chain, contract]) =>
contract ? computeNTTRateLimits_(network, token, chain as Chain) : null
)
.filter(Boolean);

const inboundCapacity = await Promise.all(inboundCapacityPromises);

return {
tokenName: token,
inboundCapacity: inboundCapacity,
};
})
);
await cloudStorageCache.save(JSON.stringify(rateLimits));
res.status(200).send('Rate limits saved');
} catch (e) {
console.error(e);
res.sendStatus(500);
}
}
107 changes: 107 additions & 0 deletions cloud_functions/src/computeTotalSupplyAndLocked.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import {
NTT_MANAGER_CONTRACT,
NTT_TOKENS,
assertEnvironmentVariable,
derivePda,
getEvmTokenDecimals,
getEvmTotalSupply,
} from '@wormhole-foundation/wormhole-monitor-common';
import { PublicKey } from '@solana/web3.js';
import {
getCustody,
getCustodyAmount,
NTTTotalSupplyAndLockedData,
} from '@wormhole-foundation/wormhole-monitor-common';
import { Network, rpc, Chain, chainToChainId } from '@wormhole-foundation/sdk-base';
import { Storage } from '@google-cloud/storage';

const storage = new Storage();
let bucketName: string = 'wormhole-ntt-cache';
if (assertEnvironmentVariable('NETWORK') === 'Testnet') {
bucketName = 'wormhole-ntt-cache-testnet';
}

const cacheBucket = storage.bucket(bucketName);
const cacheFileName = 'ntt-total-supply-and-locked.json';
const cloudStorageCache = cacheBucket.file(cacheFileName);

async function getEvmNormalizedTotalSupply(
network: Network,
token: string,
chain: Chain
): Promise<number> {
const tokenDecimals = await getEvmTokenDecimals(
rpc.rpcAddress(network, chain),
NTT_MANAGER_CONTRACT[network][token][chain]!
);
const tokenSupply = await getEvmTotalSupply(
rpc.rpcAddress(network, chain),
NTT_TOKENS[network][token][chain]!
);

return tokenSupply / 10 ** tokenDecimals;
}

async function fetchTotalSupplyAndLocked(network: Network): Promise<NTTTotalSupplyAndLockedData[]> {
const tokens = NTT_MANAGER_CONTRACT[network];
const totalSupplyVsLocked: NTTTotalSupplyAndLockedData[] = [];
for (const token in tokens) {
if (!NTT_MANAGER_CONTRACT[network][token].Solana) continue;

const programId = new PublicKey(NTT_MANAGER_CONTRACT[network][token].Solana!);
const pda = derivePda('config', programId);
const custody = await getCustody(rpc.rpcAddress(network, 'Solana'), pda.toBase58());
const locked = await getCustodyAmount(rpc.rpcAddress(network, 'Solana'), custody);

const evmTotalSupply: NTTTotalSupplyAndLockedData[] = [];
let totalSupply = 0;
for (const [supportedChain] of Object.entries(NTT_TOKENS[network][token])) {
if (supportedChain === 'Solana') continue;
const tokenSupplyNormalized = await getEvmNormalizedTotalSupply(
network,
token,
supportedChain as Chain
);

evmTotalSupply.push({
tokenName: token,
chain: chainToChainId(supportedChain as Chain),
totalSupply: tokenSupplyNormalized,
});

totalSupply += tokenSupplyNormalized;
}

totalSupplyVsLocked.push({
chain: chainToChainId('Solana'),
tokenName: token,
amountLocked: locked,
totalSupply,
evmTotalSupply,
});
}

return totalSupplyVsLocked;
}

export async function computeTotalSupplyAndLocked(req: any, res: any) {
res.set('Access-Control-Allow-Origin', '*');
if (req.method === 'OPTIONS') {
res.set('Access-Control-Allow-Methods', 'GET');
res.set('Access-Control-Allow-Headers', 'Content-Type');
res.set('Access-Control-Max-Age', '3600');
res.sendStatus(204);
return;
}

try {
const network = assertEnvironmentVariable('NETWORK') as Network;
const totalSupplyAndLocked = await fetchTotalSupplyAndLocked(network);
await cloudStorageCache.save(JSON.stringify(totalSupplyAndLocked));

res.status(200).send('Total supply and locked saved');
} catch (e) {
console.error(e);
res.sendStatus(500);
}
}
Loading

0 comments on commit d740f83

Please sign in to comment.