diff --git a/core/definitions/src/chain.ts b/core/definitions/src/chain.ts
index 072dc97ca..cfe34caa8 100644
--- a/core/definitions/src/chain.ts
+++ b/core/definitions/src/chain.ts
@@ -39,7 +39,9 @@ export abstract class ChainContext
{
}
// Get the number of decimals for a token
- async getDecimals(token: NativeAddress
| UniversalAddress | "native"): Promise {
+ async getDecimals(
+ token: NativeAddress | UniversalAddress | "native",
+ ): Promise {
return this.platform.getDecimals(this.chain, this.getRpc(), token);
}
diff --git a/core/tokenRegistry/__tests__/index.test.ts b/core/tokenRegistry/__tests__/index.test.ts
new file mode 100644
index 000000000..258ebd712
--- /dev/null
+++ b/core/tokenRegistry/__tests__/index.test.ts
@@ -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);
+ });
+ }
+ }
+ });
+ })
+});
diff --git a/core/tokenRegistry/src/foreignAssets.ts b/core/tokenRegistry/src/foreignAssets.ts
index 9af7c2749..643391277 100644
--- a/core/tokenRegistry/src/foreignAssets.ts
+++ b/core/tokenRegistry/src/foreignAssets.ts
@@ -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);
}
};
@@ -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);
@@ -24,21 +24,36 @@ 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 {
@@ -46,27 +61,34 @@ export const getForeignAddress = async (wh: Wormhole, chain: ChainName, 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(
@@ -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}`,
);
@@ -89,25 +113,33 @@ 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 = {
@@ -115,18 +147,25 @@ export const getSuggestedUpdates = async (wh: Wormhole, tokensConfig: TokensConf
[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];
-}
+};
diff --git a/core/tokenRegistry/src/scripts/checkForeignAssetConfig.ts b/core/tokenRegistry/src/scripts/checkForeignAssetConfig.ts
index 72ba443f9..693f1ccc9 100644
--- a/core/tokenRegistry/src/scripts/checkForeignAssetConfig.ts
+++ b/core/tokenRegistry/src/scripts/checkForeignAssetConfig.ts
@@ -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);
}
};
@@ -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);
})();
diff --git a/core/tokenRegistry/src/scripts/updateForeignAssetConfig.ts b/core/tokenRegistry/src/scripts/updateForeignAssetConfig.ts
index e446fca92..9c51d4391 100644
--- a/core/tokenRegistry/src/scripts/updateForeignAssetConfig.ts
+++ b/core/tokenRegistry/src/scripts/updateForeignAssetConfig.ts
@@ -1,4 +1,4 @@
-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";
@@ -6,9 +6,9 @@ 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;
/**
@@ -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);
}
/**
@@ -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);
-})();
\ No newline at end of file
+ await checkEnvConfig("Testnet", TESTNET_TOKENS);
+ await checkEnvConfig("Mainnet", MAINNET_TOKENS);
+})();
diff --git a/core/tokenRegistry/src/tokens/mainnetTokens.json b/core/tokenRegistry/src/tokens/mainnetTokens.json
index 41741e58c..43fa1a776 100644
--- a/core/tokenRegistry/src/tokens/mainnetTokens.json
+++ b/core/tokenRegistry/src/tokens/mainnetTokens.json
@@ -1,9 +1,10 @@
{
"Ethereum": {
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0": {
- "name:": "wstETH",
+ "name": "wstETH",
"symbol": "wstETH",
"nativeChain": "Ethereum",
+ "decimals": 18,
"foreignAssets": {
"Arbitrum": {
"address": "0xf2717122Dfdbe988ae811E7eFB157aAa07Ff9D0F",
@@ -22,7 +23,7 @@
"0x18084fbA666a33d37592fA2633fD49a74DD93a88": {
"name": "tBTC",
"symbol": "tBTC",
- "nativeChain": "ethereum",
+ "nativeChain": "Ethereum",
"decimals": 18,
"foreignAssets": {
"Polygon": {
@@ -119,7 +120,7 @@
"name": "USDC (Ethereum)",
"symbol": "USDC",
"nativeChain": "Ethereum",
- "deimals": 6,
+ "decimals": 6,
"foreignAssets": {
"Bsc": {
"address": "0xB04906e95AB5D797aDA81508115611fee694c2b3",
@@ -175,7 +176,7 @@
"name": "WBTC",
"symbol": "WBTC",
"nativeChain": "Ethereum",
- "deimals": 8,
+ "decimals": 8,
"foreignAssets": {
"Bsc": {
"address": "0x43359676E1A3F9FbB5de095333f8e9c1B46dFA44",
@@ -231,7 +232,7 @@
"name": "USDT",
"symbol": "USDT",
"nativeChain": "Ethereum",
- "deimals": 6,
+ "decimals": 6,
"foreignAssets": {
"Bsc": {
"address": "0x524bC91Dc82d6b90EF29F76A3ECAaBAffFD490Bc",
@@ -283,7 +284,7 @@
"name": "DAI",
"symbol": "DAI",
"nativeChain": "Ethereum",
- "deimals": 18,
+ "decimals": 18,
"foreignAssets": {
"Bsc": {
"address": "0x3413a030EF81a3dD5a302F4B4D11d911e12ed337",
@@ -335,7 +336,7 @@
"name": "BUSD",
"symbol": "BUSD",
"nativeChain": "Ethereum",
- "deimals": 18,
+ "decimals": 18,
"foreignAssets": {
"Bsc": {
"address": "0x035de3679E692C471072d1A09bEb9298fBB2BD31",
@@ -1344,4 +1345,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/core/tokenRegistry/src/tokens/testnetTokens.json b/core/tokenRegistry/src/tokens/testnetTokens.json
index 3e50e0266..f3b1db5e4 100644
--- a/core/tokenRegistry/src/tokens/testnetTokens.json
+++ b/core/tokenRegistry/src/tokens/testnetTokens.json
@@ -1013,4 +1013,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/core/tokenRegistry/src/types.ts b/core/tokenRegistry/src/types.ts
index ad2e9ee88..3b6e777d5 100644
--- a/core/tokenRegistry/src/types.ts
+++ b/core/tokenRegistry/src/types.ts
@@ -14,7 +14,7 @@ export type TokenConfig = {
nativeChain: ChainName;
decimals: number;
foreignAssets?: ForeignAssetsCache;
-}
+};
export type TokensConfig = {
- [chain in ChainName]?: { [key: string]: TokenConfig }
+ [chain in ChainName]?: { [key: string]: TokenConfig };
};
diff --git a/platforms/cosmwasm/src/platformUtils.ts b/platforms/cosmwasm/src/platformUtils.ts
index d5e251e02..33a28cb29 100644
--- a/platforms/cosmwasm/src/platformUtils.ts
+++ b/platforms/cosmwasm/src/platformUtils.ts
@@ -55,17 +55,13 @@ export module CosmwasmUtils {
export async function getDecimals(
chain: ChainName,
rpc: CosmWasmClient,
- token: UniversalOrNative<'Cosmwasm'> | "native",
+ token: UniversalOrNative<"Cosmwasm"> | "native",
): Promise {
- if (token === "native")
- return nativeDecimals(CosmwasmPlatform.platform);
-
- const { decimals } = await rpc.queryContractSmart(
- token.toString(),
- {
- token_info: {},
- },
- );
+ if (token === "native") return nativeDecimals(CosmwasmPlatform.platform);
+
+ const { decimals } = await rpc.queryContractSmart(token.toString(), {
+ token_info: {},
+ });
return decimals;
}
@@ -73,7 +69,7 @@ export module CosmwasmUtils {
chain: ChainName,
rpc: CosmWasmClient,
walletAddress: string,
- token: UniversalOrNative<'Cosmwasm'> | "native",
+ token: UniversalOrNative<"Cosmwasm"> | "native",
): Promise {
if (token === "native") {
const { amount } = await rpc.getBalance(
@@ -83,10 +79,7 @@ export module CosmwasmUtils {
return BigInt(amount);
}
- const { amount } = await rpc.getBalance(
- walletAddress,
- token.toString(),
- );
+ const { amount } = await rpc.getBalance(walletAddress, token.toString());
return BigInt(amount);
}