Skip to content

Commit

Permalink
add: tests and fix typos from manual edits
Browse files Browse the repository at this point in the history
  • Loading branch information
anondev2323 committed Oct 13, 2023
1 parent ecb89ca commit d4fde7d
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 87 deletions.
4 changes: 3 additions & 1 deletion core/definitions/src/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ export abstract class ChainContext<P extends PlatformName> {
}

// Get the number of decimals for a token
async getDecimals(token: NativeAddress<P> | UniversalAddress | "native"): Promise<bigint> {
async getDecimals(
token: NativeAddress<P> | UniversalAddress | "native",
): Promise<bigint> {
return this.platform.getDecimals(this.chain, this.getRpc(), token);
}

Expand Down
31 changes: 31 additions & 0 deletions core/tokenRegistry/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as fs from 'fs';
import { TokensConfig } from '../src/types';
import { Network } from '@wormhole-foundation/connect-sdk';

const testnetTokens = fs.readFileSync('src/tokens/testnetTokens.json', 'utf-8');
const TESTNET_TOKENS = JSON.parse(testnetTokens) as TokensConfig;
const mainnetTokens = fs.readFileSync('src/tokens/mainnetTokens.json', 'utf-8');
const MAINNET_TOKENS = JSON.parse(mainnetTokens) as TokensConfig;

const getTokens = (network: Network) => {
return network === 'Mainnet' ? MAINNET_TOKENS : TESTNET_TOKENS;
}

describe('token config format', () => {
const networks: Network[] = ['Mainnet', 'Testnet'];
networks.forEach(network => {
const tokens = getTokens(network);
describe(`All ${network} token details are set`, () => {
for (const [chain, chainTokens] of Object.entries(tokens)) {
for (const [address, tokenConfig] of Object.entries(chainTokens)) {
test(`${chain} ${address} details are set`, () => {
expect(tokenConfig.name).toBeTruthy();
expect(tokenConfig.symbol).toBeTruthy();
expect(tokenConfig.decimals).toBeTruthy();
expect(tokenConfig.nativeChain).toBe(chain);
});
}
}
});
})
});
97 changes: 68 additions & 29 deletions core/tokenRegistry/src/foreignAssets.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// patch out annoying logs
const info = console.info;
console.info = function (x: any, ...rest: any) {
if (x !== 'secp256k1 unavailable, reverting to browser version') {
if (x !== "secp256k1 unavailable, reverting to browser version") {
info(x, ...rest);
}
};
Expand All @@ -11,7 +11,7 @@ console.warn = function (x: any, ...rest: any) {
!x
.toString()
.startsWith(
'Error: Error: RPC Validation Error: The response returned from RPC server does not match the TypeScript definition. This is likely because the SDK version is not compatible with the RPC server.',
"Error: Error: RPC Validation Error: The response returned from RPC server does not match the TypeScript definition. This is likely because the SDK version is not compatible with the RPC server.",
)
) {
warn(x, ...rest);
Expand All @@ -24,49 +24,71 @@ import { TokenId, Wormhole, toNative } from "@wormhole-foundation/connect-sdk";

// TODO: Question: How do we handle if a user tries to perform an action for a chain/platform which isn't installed??
// const supportedPlatforms: PlatformName[] = ['Evm', 'Solana'];
const supportedChains: ChainName[] = ['Ethereum', 'Polygon', 'Celo', 'Moonbeam', 'Fantom', 'Avalanche', 'Bsc', 'Optimism', 'Arbitrum', 'Solana']
const supportedChains: ChainName[] = [
"Ethereum",
"Polygon",
"Celo",
"Moonbeam",
"Fantom",
"Avalanche",
"Bsc",
"Optimism",
"Arbitrum",
"Solana",
];

export const isSupportedChain = (chain: ChainName) => {
return supportedChains.includes(chain);
}
};

export const createTokenId = (chain: ChainName, address: string) => {
if (!isSupportedChain(chain)) return;
return {
chain,
address: toNative(chain, address),
}
}
};
};

export const getForeignAddress = async (wh: Wormhole, chain: ChainName, tokenId: TokenId) => {
export const getForeignAddress = async (
wh: Wormhole,
chain: ChainName,
tokenId: TokenId,
) => {
if (!isSupportedChain(chain)) return;
let foreignAddress: string | null = null;
try {
const foreignId = await wh.getWrappedAsset(chain, tokenId);
foreignAddress = foreignId.address.toString();
} catch (e: any) {
if (
e?.message === '3104 RPC not configured' ||
e?.message === 'wormchain RPC not configured'
e?.message === "3104 RPC not configured" ||
e?.message === "wormchain RPC not configured"
) {
// do not throw on wormchain errors
} else if (e?.message.includes('is not a wrapped asset')) {
} else if (e?.message.includes("is not a wrapped asset")) {
// do not throw if wrapped asset does not exist
} else {
// log error but keep going
console.error(e)
console.error(e);
}
}
return foreignAddress;
}
};

export const getForeignAssetsData = async (wh: Wormhole, chain: ChainName, tokenId: TokenId | undefined, foreignAssetsCache: ForeignAssetsCache | undefined) => {
export const getForeignAssetsData = async (
wh: Wormhole,
chain: ChainName,
tokenId: TokenId | undefined,
foreignAssetsCache: ForeignAssetsCache | undefined,
) => {
if (!tokenId) return;
let updates: ForeignAssetsCache = {};
for (const foreignChain of chains) {
const isSupported = isSupportedChain(foreignChain);
if (foreignChain !== tokenId.chain && isSupported) {
const configForeignAddress = foreignAssetsCache ? foreignAssetsCache[foreignChain] : undefined;
const configForeignAddress = foreignAssetsCache
? foreignAssetsCache[foreignChain]
: undefined;
const foreignAddress = await getForeignAddress(wh, foreignChain, tokenId);
if (foreignAddress) {
const foreignDecimals = await wh.getDecimals(
Expand All @@ -78,7 +100,9 @@ export const getForeignAssetsData = async (wh: Wormhole, chain: ChainName, token
throw new Error(
`❌ Invalid foreign address detected! Env: ${wh.conf.network}, Existing Address: ${configForeignAddress.address}, Chain: ${chain}, Expected: ${foreignAddress}, Received: ${configForeignAddress.address}`,
);
} else if (configForeignAddress.decimals !== Number(foreignDecimals)) {
} else if (
configForeignAddress.decimals !== Number(foreignDecimals)
) {
throw new Error(
`❌ Invalid foreign decimals detected! Env: ${wh.conf.network}, Existing Address: ${configForeignAddress.address}, Chain: ${chain}, Expected: ${foreignDecimals}, Received: ${configForeignAddress.decimals}`,
);
Expand All @@ -89,44 +113,59 @@ export const getForeignAssetsData = async (wh: Wormhole, chain: ChainName, token
const update = {
[foreignChain]: {
address: foreignAddress,
decimals: Number(foreignDecimals)
}
}
updates = { ...updates, ...update }
decimals: Number(foreignDecimals),
},
};
updates = { ...updates, ...update };
}
}
}
}
return updates;
}
};

export const getSuggestedUpdates = async (wh: Wormhole, tokensConfig: TokensConfig) => {
export const getSuggestedUpdates = async (
wh: Wormhole,
tokensConfig: TokensConfig,
) => {
let suggestedUpdates: TokensConfig = {};
let numUpdates = 0;

for (const [chain, chainTokensConfig] of Object.entries(tokensConfig)) {
for (const [token, config] of Object.entries(chainTokensConfig)) {
const tokenId = createTokenId(chain as ChainName, token);
const updates = await getForeignAssetsData(wh, chain as ChainName, tokenId, config.foreignAssets);
const updates = await getForeignAssetsData(
wh,
chain as ChainName,
tokenId,
config.foreignAssets,
);
if (updates && Object.values(updates).length > 0) {
numUpdates += Object.values(updates).length;
suggestedUpdates = {
...suggestedUpdates,
[chain]: {
...(suggestedUpdates[chain as ChainName] || {}),
[token]: {
...(suggestedUpdates[chain as ChainName] ? suggestedUpdates[chain as ChainName]![token] || {} : {}),
...(suggestedUpdates[chain as ChainName]
? suggestedUpdates[chain as ChainName]![token] || {}
: {}),
foreignAssets: {
...(suggestedUpdates[chain as ChainName] ? suggestedUpdates[chain as ChainName]![token] ? suggestedUpdates[chain as ChainName]![token]!.foreignAssets : {} : {}),
...(suggestedUpdates[chain as ChainName]
? suggestedUpdates[chain as ChainName]![token]
? suggestedUpdates[chain as ChainName]![token]!
.foreignAssets
: {}
: {}),
...updates,
}
}
}
}
},
},
},
};
}
}
}
// console.log(`${numUpdates} updates available`);
// console.log(JSON.stringify(suggestedUpdates, null, 4));
return [numUpdates, suggestedUpdates];
}
};
35 changes: 17 additions & 18 deletions core/tokenRegistry/src/scripts/checkForeignAssetConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// patch out annoying logs
const info = console.info;
console.info = function (x: any, ...rest: any) {
if (x !== 'secp256k1 unavailable, reverting to browser version') {
if (x !== "secp256k1 unavailable, reverting to browser version") {
info(x, ...rest);
}
};
Expand All @@ -11,47 +11,46 @@ console.warn = function (x: any, ...rest: any) {
!x
.toString()
.startsWith(
'Error: Error: RPC Validation Error: The response returned from RPC server does not match the TypeScript definition. This is likely because the SDK version is not compatible with the RPC server.',
"Error: Error: RPC Validation Error: The response returned from RPC server does not match the TypeScript definition. This is likely because the SDK version is not compatible with the RPC server.",
)
) {
warn(x, ...rest);
}
};

import * as fs from 'fs';
import * as fs from "fs";
import { Network } from "@wormhole-foundation/sdk-base";
import { Wormhole } from "@wormhole-foundation/connect-sdk";
import { EvmPlatform } from "@wormhole-foundation/connect-sdk-evm";
import { SolanaPlatform } from "@wormhole-foundation/connect-sdk-solana";
import { getSuggestedUpdates } from '../foreignAssets';
import { getSuggestedUpdates } from "../foreignAssets";
import { TokensConfig } from "../types";

const testnetTokens = fs.readFileSync('src/tokens/testnetTokens.json', 'utf-8');
const testnetTokens = fs.readFileSync("src/tokens/testnetTokens.json", "utf-8");
const TESTNET_TOKENS = JSON.parse(testnetTokens) as TokensConfig;
const mainnetTokens = fs.readFileSync('src/tokens/mainnetTokens.json', 'utf-8');
const mainnetTokens = fs.readFileSync("src/tokens/mainnetTokens.json", "utf-8");
const MAINNET_TOKENS = JSON.parse(mainnetTokens) as TokensConfig;

// warning: be careful optimizing the RPC calls in this script, you may 429 yourself
// slow and steady, or something like that
const checkEnvConfig = async (
env: Network,
tokensConfig: TokensConfig,
) => {
const checkEnvConfig = async (env: Network, tokensConfig: TokensConfig) => {
const wh = new Wormhole(env, [EvmPlatform, SolanaPlatform]);

const [numUpdates, suggestedUpdates] = await getSuggestedUpdates(wh, tokensConfig);
if (numUpdates as number > 0) {
const [numUpdates, suggestedUpdates] = await getSuggestedUpdates(
wh,
tokensConfig,
);
if ((numUpdates as number) > 0) {
console.log(`
${numUpdates} updates available. To update, run:\n
npm run updateForeignAssets`
);
npm run updateForeignAssets`);
console.log(JSON.stringify(suggestedUpdates, null, 4));
} else {
console.log('Up to date')
console.log("Up to date");
}
}
};

(async () => {
await checkEnvConfig('Testnet', TESTNET_TOKENS);
await checkEnvConfig('Mainnet', MAINNET_TOKENS);
await checkEnvConfig("Testnet", TESTNET_TOKENS);
await checkEnvConfig("Mainnet", MAINNET_TOKENS);
})();
26 changes: 13 additions & 13 deletions core/tokenRegistry/src/scripts/updateForeignAssetConfig.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as fs from 'fs';
import * as fs from "fs";
import { Network } from "@wormhole-foundation/sdk-base";
import { Wormhole } from "@wormhole-foundation/connect-sdk";
import { EvmPlatform } from "@wormhole-foundation/connect-sdk-evm";
import { SolanaPlatform } from "@wormhole-foundation/connect-sdk-solana";
import { getSuggestedUpdates } from "../foreignAssets";
import { TokensConfig } from "../types";

const testnetTokens = fs.readFileSync('src/tokens/testnetTokens.json', 'utf-8');
const testnetTokens = fs.readFileSync("src/tokens/testnetTokens.json", "utf-8");
const TESTNET_TOKENS = JSON.parse(testnetTokens) as TokensConfig;
const mainnetTokens = fs.readFileSync('src/tokens/mainnetTokens.json', 'utf-8');
const mainnetTokens = fs.readFileSync("src/tokens/mainnetTokens.json", "utf-8");
const MAINNET_TOKENS = JSON.parse(mainnetTokens) as TokensConfig;

/**
Expand All @@ -17,7 +17,7 @@ const MAINNET_TOKENS = JSON.parse(mainnetTokens) as TokensConfig;
* @returns {boolean}
*/
export function isObject(item: any) {
return (item && typeof item === 'object' && !Array.isArray(item));
return item && typeof item === "object" && !Array.isArray(item);
}

/**
Expand Down Expand Up @@ -45,20 +45,20 @@ export function mergeDeep(target: any, ...sources: any) {

// warning: be careful optimizing the RPC calls in this script, you may 429 yourself
// slow and steady, or something like that
const checkEnvConfig = async (
env: Network,
tokensConfig: TokensConfig,
) => {
const checkEnvConfig = async (env: Network, tokensConfig: TokensConfig) => {
const wh = new Wormhole(env, [EvmPlatform, SolanaPlatform]);

const data = await getSuggestedUpdates(wh, tokensConfig);
const suggestedUpdates = data[1] as TokensConfig;
const newConfig = mergeDeep(tokensConfig, suggestedUpdates);
const filePath = env === 'Mainnet' ? 'src/tokens/mainnetTokens.json' : 'src/tokens/testnetTokens.json';
const filePath =
env === "Mainnet"
? "src/tokens/mainnetTokens.json"
: "src/tokens/testnetTokens.json";
fs.writeFileSync(filePath, JSON.stringify(newConfig, null, 2));
}
};

(async () => {
await checkEnvConfig('Testnet', TESTNET_TOKENS);
await checkEnvConfig('Mainnet', MAINNET_TOKENS);
})();
await checkEnvConfig("Testnet", TESTNET_TOKENS);
await checkEnvConfig("Mainnet", MAINNET_TOKENS);
})();
Loading

0 comments on commit d4fde7d

Please sign in to comment.