Skip to content

Commit

Permalink
Merge pull request #724 from chainapsis/delivan/add-evm
Browse files Browse the repository at this point in the history
Add evm folder & Update scripts
  • Loading branch information
delivan authored Jul 22, 2024
2 parents a2cb6c5 + 910edf6 commit f6f695b
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 20 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pull-request-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
with:
files: |
cosmos/**
evm/**
- name: Validate changed files
run: |
Expand Down
36 changes: 36 additions & 0 deletions evm/eip155:1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"rpc": "https://evm-1.keplr.app",
"websocket": "wss://evm-1.keplr.app/websocket",
"chainId": "eip155:1",
"chainName": "Ethereum",
"chainSymbolImageUrl": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/eip155:1/chain.png",
"bip44": {
"coinType": 60
},
"currencies": [
{
"coinDenom": "ETH",
"coinMinimalDenom": "ethereum-native",
"coinDecimals": 18,
"coinGeckoId": "ethereum",
"coinImageUrl": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/eip155:1/ethereum-native.png"
},
{
"coinDenom": "USDC",
"coinMinimalDenom": "erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"coinDecimals": 6,
"coinGeckoId": "usd-coin",
"coinImageUrl": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/eip155:1/erc20/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.png"
}
],
"feeCurrencies": [
{
"coinDenom": "ETH",
"coinMinimalDenom": "ethereum-native",
"coinDecimals": 18,
"coinGeckoId": "ethereum",
"coinImageUrl": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/eip155:1/ethereum-native.png"
}
],
"features": []
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/eip155:1/ethereum-native.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const nativeMainnetChainIdentifiers: string[] = [
"dimension_37",
"pryzm",
"zetachain_7000",
"eip155:1",
];

export const nativeTestnetChainIdentifiers: string[] = [
Expand Down
12 changes: 10 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { checkImageSize, validateChainInfoFromPath } from "./validate";
import {
checkImageSize,
validateCosmosChainInfoFromPath,
validateEvmChainInfoFromPath,
} from "./validate";
import libPath from "path";
import { ChainIdHelper } from "@keplr-wallet/cosmos";
import {
Expand All @@ -17,7 +21,11 @@ const main = async () => {

const path = args[0];

const chainInfo = await validateChainInfoFromPath(path);
const isEVMOnlyChain = path.includes("eip155:");

const chainInfo = isEVMOnlyChain
? await validateEvmChainInfoFromPath(path)
: await validateCosmosChainInfoFromPath(path);

const isNativeSupported = (() => {
const chainIdentifier = ChainIdHelper.parse(chainInfo.chainId).identifier;
Expand Down
44 changes: 31 additions & 13 deletions src/schedule.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { readdirSync } from "fs";
import { validateChainInfoFromPath } from "./validate";
import {
validateCosmosChainInfoFromPath,
validateEvmChainInfoFromPath,
} from "./validate";
import * as core from "@actions/core";

const main = async () => {
const jsonFiles = readdirSync("cosmos");
const cosmosJsonFiles = readdirSync("cosmos");
const evmJsonFiles = readdirSync("evm");
core.setOutput("hasError", false);

let errorMessages: (
Expand All @@ -13,18 +17,32 @@ const main = async () => {
}
| undefined
)[] = await Promise.all(
jsonFiles.map(async (file) => {
try {
await validateChainInfoFromPath(`cosmos/${file}`);
} catch (e) {
return {
file,
error: e,
};
}
cosmosJsonFiles
.map(async (file) => {
try {
await validateCosmosChainInfoFromPath(`cosmos/${file}`);
} catch (e) {
return {
file,
error: e,
};
}

return undefined;
}),
return undefined;
})
.concat(
evmJsonFiles.map(async (file) => {
try {
await validateEvmChainInfoFromPath(`evm/${file}`);
} catch (e) {
return {
file,
error: e,
};
}
return undefined;
}),
),
);

errorMessages = errorMessages.filter((e) => e != null);
Expand Down
126 changes: 121 additions & 5 deletions src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const fileToChainInfo = (filePath: string) => {
return chainInfo;
};

export const validateChainInfoFromPath = async (
export const validateCosmosChainInfoFromPath = async (
path: string,
): Promise<ChainInfo> => {
const parsed = libPath.parse(path);
Expand All @@ -35,10 +35,10 @@ export const validateChainInfoFromPath = async (
}

// validate chain info
return await validateChainInfo(parsed.name, chainInfo);
return await validateCosmosChainInfo(parsed.name, chainInfo);
};

export const validateChainInfo = async (
export const validateCosmosChainInfo = async (
chainIdentifier: string,
chainInfo: ChainInfo,
): Promise<ChainInfo> => {
Expand Down Expand Up @@ -134,6 +134,121 @@ export const validateChainInfo = async (
return chainInfo;
};

export const validateEvmChainInfoFromPath = async (
path: string,
): Promise<ChainInfo> => {
const parsed = libPath.parse(path);
if (parsed.ext !== ".json") {
throw new Error("File is not json");
}

// get json from file
const file = readFileSync(path, "utf-8");
const chainInfo: Omit<ChainInfo, "rest"> & { websocket: string } =
JSON.parse(file);

// validate chain info
return await validateEvmChainInfo(parsed.name, chainInfo);
};

export const validateEvmChainInfo = async (
chainIdentifier: string,
evmChainInfo: Omit<ChainInfo, "rest"> & { websocket: string },
): Promise<ChainInfo> => {
// Check chain identifier
const parsedChainId = ChainIdHelper.parse(evmChainInfo.chainId).identifier;
if (parsedChainId !== chainIdentifier) {
throw new Error(
`Chain identifier unmatched: (expected: ${parsedChainId}, actual: ${chainIdentifier})`,
);
}

const evmChainId = parseInt(parsedChainId.replace("eip155:", ""));
if (isNaN(evmChainId)) {
throw new Error(
"Invalid chain identifier. It should be eip155:{integer greater-than-zero}",
);
}

const { websocket, features, ...restEVMChainInfo } = evmChainInfo;
const chainInfoCandidate = {
...restEVMChainInfo,
rest: evmChainInfo.rpc,
evm: {
chainId: evmChainId,
rpc: evmChainInfo.rpc,
websocket,
},
features: ["eth-address-gen", "eth-key-sign"].concat(features ?? []),
};
const prev = sortedJsonByKeyStringify(chainInfoCandidate);
// validate chain information
const chainInfo = await (async () => {
try {
return await validateBasicChainInfoType(chainInfoCandidate);
} catch (e: any) {
// Ignore bech32Config error
if (e.message === `"bech32Config" is required`) {
return chainInfoCandidate;
} else {
throw e;
}
}
})();
if (sortedJsonByKeyStringify(chainInfo) !== prev) {
throw new Error("Chain info has unknown field");
}

if (chainInfo.evm == null) {
throw new Error("Something went wrong with 'evm' field");
}

// Check currencies
checkCurrencies(chainInfo);

for (const feature of chainInfo.features ?? []) {
if (!NonRecognizableChainFeatures.includes(feature)) {
throw new Error(
`Only non recognizable feature should be provided: ${feature}`,
);
}
}

if (chainInfo.beta != null) {
throw new Error("Should not set 'beta' field");
}

if (chainInfo.rpc.startsWith("http://")) {
throw new Error(
"RPC endpoints cannot be set as HTTP, please set them as HTTPS",
);
}

await checkEvmRpcConnectivity(chainInfo.evm.chainId, chainInfo.rpc);

// check coinGecko vaild
const coinGeckoIds = new Set<string>();
for (const currency of chainInfo.currencies) {
if (currency.coinGeckoId) {
coinGeckoIds.add(currency.coinGeckoId);
}
}

for (const currency of chainInfo.feeCurrencies) {
if (currency.coinGeckoId) {
coinGeckoIds.add(currency.coinGeckoId);
}
}

if (chainInfo.stakeCurrency?.coinGeckoId) {
coinGeckoIds.add(chainInfo.stakeCurrency.coinGeckoId);
}

await checkCoinGeckoIds(...Array.from(coinGeckoIds));

return chainInfo;
};

export const checkImageSize = (path: string) => {
const dimensions = sizeOf(path);
if (dimensions.width !== 256 || dimensions.height !== 256) {
Expand Down Expand Up @@ -200,9 +315,10 @@ export const checkCurrencies = (chainInfo: ChainInfo) => {

// Check currencies
for (const currency of chainInfo.currencies) {
if (new DenomHelper(currency.coinMinimalDenom).type !== "native") {
const denomHelper = new DenomHelper(currency.coinMinimalDenom);
if (denomHelper.type !== "native" && denomHelper.type !== "erc20") {
throw new Error(
`Do not provide not native token to currencies: ${currency.coinMinimalDenom}`,
`Do not provide not native token or ERC20 token to currencies: ${currency.coinMinimalDenom}`,
);
}

Expand Down

0 comments on commit f6f695b

Please sign in to comment.