-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cb6c92c
commit 4b2cf3f
Showing
22 changed files
with
2,768 additions
and
57 deletions.
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
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
Empty file.
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,3 @@ | ||
# Tokens Registry | ||
|
||
Cache of token details and foreign asset addresses |
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,39 @@ | ||
{ | ||
"name": "@wormhole-foundation/sdk-token-registry", | ||
"version": "0.1.4", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/wormhole-foundation/connect-sdk.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/wormhole-foundation/connect-sdk/issues" | ||
}, | ||
"homepage": "https://github.com/wormhole-foundation/connect-sdk#readme", | ||
"directories": { | ||
"test": "__tests__" | ||
}, | ||
"main": "./dist/cjs/index.js", | ||
"module": "./dist/esm/index.js", | ||
"types": "./dist/esm/index.d.ts", | ||
"files": [ | ||
"dist/**/*", | ||
"src/**/*" | ||
], | ||
"scripts": { | ||
"test": "jest --config ../../jest.config.ts __tests__/*.ts", | ||
"build:cjs": "tsc -p ./tsconfig.cjs.json", | ||
"build:esm": "tsc -p ./tsconfig.esm.json", | ||
"build": "npm run build:cjs && npm run build:esm", | ||
"rebuild": "npm run clean && npm run build:cjs && npm run build:esm", | ||
"clean": "rm -rf ./dist && rm -f ./*.tsbuildinfo", | ||
"lint": "npm run prettier && eslint --fix", | ||
"prettier": "prettier --write ./src", | ||
"updateForeignAssets": "npx ts-node ./src/scripts/updateForeignAssetConfig" | ||
}, | ||
"dependencies": { | ||
"@wormhole-foundation/connect-sdk": "*", | ||
"@wormhole-foundation/connect-sdk-evm": "*", | ||
"@wormhole-foundation/connect-sdk-solana": "*", | ||
"@wormhole-foundation/connect-sdk-cosmwasm": "*" | ||
} | ||
} |
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,132 @@ | ||
// patch out annoying logs | ||
const info = console.info; | ||
console.info = function (x: any, ...rest: any) { | ||
if (x !== 'secp256k1 unavailable, reverting to browser version') { | ||
info(x, ...rest); | ||
} | ||
}; | ||
const warn = console.warn; | ||
console.warn = function (x: any, ...rest: any) { | ||
if ( | ||
!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.', | ||
) | ||
) { | ||
warn(x, ...rest); | ||
} | ||
}; | ||
|
||
import { ChainName, chains } from "@wormhole-foundation/sdk-base"; | ||
import { ForeignAssetsCache, TokensConfig } from "./types"; | ||
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'] | ||
|
||
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) => { | ||
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' | ||
) { | ||
// do not throw on wormchain errors | ||
} 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) | ||
} | ||
} | ||
return foreignAddress; | ||
} | ||
|
||
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 foreignAddress = await getForeignAddress(wh, foreignChain, tokenId); | ||
if (foreignAddress) { | ||
const foreignDecimals = await wh.getDecimals( | ||
foreignChain, | ||
toNative(foreignChain, foreignAddress), | ||
); | ||
if (configForeignAddress) { | ||
if (configForeignAddress.address !== foreignAddress) { | ||
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)) { | ||
throw new Error( | ||
`❌ Invalid foreign decimals detected! Env: ${wh.conf.network}, Existing Address: ${configForeignAddress.address}, Chain: ${chain}, Expected: ${foreignDecimals}, Received: ${configForeignAddress.decimals}`, | ||
); | ||
} else { | ||
// console.log('✅ Config matches'); | ||
} | ||
} else { | ||
const update = { | ||
[foreignChain]: { | ||
address: foreignAddress, | ||
decimals: Number(foreignDecimals) | ||
} | ||
} | ||
updates = { ...updates, ...update } | ||
} | ||
} | ||
} | ||
} | ||
return updates; | ||
} | ||
|
||
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); | ||
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] || {} : {}), | ||
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]; | ||
} |
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,57 @@ | ||
// patch out annoying logs | ||
const info = console.info; | ||
console.info = function (x: any, ...rest: any) { | ||
if (x !== 'secp256k1 unavailable, reverting to browser version') { | ||
info(x, ...rest); | ||
} | ||
}; | ||
const warn = console.warn; | ||
console.warn = function (x: any, ...rest: any) { | ||
if ( | ||
!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.', | ||
) | ||
) { | ||
warn(x, ...rest); | ||
} | ||
}; | ||
|
||
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 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; | ||
|
||
// 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 wh = new Wormhole(env, [EvmPlatform, SolanaPlatform]); | ||
|
||
const [numUpdates, suggestedUpdates] = await getSuggestedUpdates(wh, tokensConfig); | ||
if (numUpdates as number > 0) { | ||
console.log(` | ||
${numUpdates} updates available. To update, run:\n | ||
npm run updateForeignAssets` | ||
); | ||
console.log(JSON.stringify(suggestedUpdates, null, 4)); | ||
} else { | ||
console.log('Up to date') | ||
} | ||
} | ||
|
||
(async () => { | ||
await checkEnvConfig('Testnet', TESTNET_TOKENS); | ||
await checkEnvConfig('Mainnet', MAINNET_TOKENS); | ||
})(); |
Oops, something went wrong.