Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/cosmos/.mocharc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"require": ["ts-node/register"],
"spec": "test/**/*.test.ts",
"timeout": 15000
"timeout": 1000000
}
43 changes: 43 additions & 0 deletions modules/cosmos/configs/mainnet.module.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,48 @@
},
"bank": {
"account": "ethm1dakgyqjulg29m5fmv992g2y66m9g2mjn6hahwg"
},
"ibc": {
"chains": [
{
"dstChain": {
"account": {
"mnemonic": ""
},
"evm": true,
"chainId": "xrplevm_1440000-1",
"rpcUrl": "http://cosmos-rpc.xrplevm.org:26657",
"prefix": "ethm",
"denom": "axrp",
"amount": "5000",
"channel": "",
"gas": {
"amount": "40000000000000000",
"gas": "200000"
}
},
"srcChain": {
"account": {
"mnemonic": ""
},
"evm": false,
"chainId": "osmo-mainnet-1",
"rpcUrl": "https://rpc.osmosis.zone",
"prefix": "osmo",
"denom": "uosmo",
"amount": "5000",
"gas": {
"amount": "200000",
"gas": "200000"
},
"channel": ""
},
"port": "transfer"
}
],
"heightBuffer": 1000,
"timeoutMinutes": 10,
"maxIterations": 12,
"delay": 10000
}
}
45 changes: 45 additions & 0 deletions modules/cosmos/configs/testnet.module.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,50 @@
},
"bank": {
"account": "ethm1dakgyqjulg29m5fmv992g2y66m9g2mjn6hahwg"
},
"ibc": {
"chains": [
{
"dstChain": {
"account": {
"mnemonic": "harsh harsh mean pool tell oval cancel deal unit strategy deny pool",
"address": "ethm1dny09udcpxg2j6440fuk2m6wajz6249tgu2znt"
},
"evm": true,
"chainId": "xrplevm_1449000-1",
"rpcUrl": "http://cosmos.testnet.xrplevm.org:26657",
"prefix": "ethm",
"denom": "axrp",
"amount": "5000",
"channel": "channel-2",
"gas": {
"amount": "40000000000000000",
"gas": "200000"
}
},
"srcChain": {
"account": {
"mnemonic": "harsh harsh mean pool tell oval cancel deal unit strategy deny pool",
"address": "cosmos1dakgyqjulg29m5fmv992g2y66m9g2mjn6hahwg"
},
"evm": false,
"chainId": "osmo-test-5",
"rpcUrl": "https://rpc.testnet.osmosis.zone",
"prefix": "osmo",
"denom": "uosmo",
"amount": "5000",
"gas": {
"amount": "200000",
"gas": "200000"
},
"channel": "channel-10361"
},
"port": "transfer"
}
],
"heightBuffer": 1000,
"timeoutMinutes": 10,
"maxIterations": 12,
"delay": 10000
}
}
45 changes: 45 additions & 0 deletions modules/cosmos/module.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,50 @@
},
"bank": {
"account": "ethm1dakgyqjulg29m5fmv992g2y66m9g2mjn6hahwg"
},
"ibc": {
"chains": [
{
"dstChain": {
"account": {
"mnemonic": "harsh harsh mean pool tell oval cancel deal unit strategy deny pool",
"address": "ethm1dny09udcpxg2j6440fuk2m6wajz6249tgu2znt"
},
"evm": true,
"chainId": "xrplevm_1449000-1",
"rpcUrl": "http://cosmos.testnet.xrplevm.org:26657",
"prefix": "ethm",
"denom": "axrp",
"amount": "5000",
"channel": "channel-2",
"gas": {
"amount": "40000000000000000",
"gas": "200000"
}
},
"srcChain": {
"account": {
"mnemonic": "harsh harsh mean pool tell oval cancel deal unit strategy deny pool",
"address": "cosmos1dakgyqjulg29m5fmv992g2y66m9g2mjn6hahwg"
},
"evm": false,
"chainId": "osmo-test-5",
"rpcUrl": "https://rpc.testnet.osmosis.zone",
"prefix": "osmo",
"denom": "uosmo",
"amount": "5000",
"gas": {
"amount": "200000",
"gas": "200000"
},
"channel": "channel-10361"
},
"port": "transfer"
}
],
"heightBuffer": 1000,
"timeoutMinutes": 10,
"maxIterations": 12,
"delay": 10000
}
}
9 changes: 8 additions & 1 deletion modules/cosmos/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
},
"license": "ISC",
"dependencies": {
"@cosmjs/amino": "^0.33.1",
"@cosmjs/crypto": "^0.33.1",
"@cosmjs/encoding": "^0.33.1",
"@cosmjs/math": "^0.33.1",
"@cosmjs/proto-signing": "^0.33.1",
"@cosmjs/stargate": "^0.33.0",
"@cosmjs/tendermint-rpc": "^0.33.1",
"@cosmjs/utils": "^0.33.1",
"@types/chai": "^5.0.1",
"cosmjs-types": "^0.9.0",
"mocha": "^11.1.0"
Expand All @@ -23,7 +28,9 @@
"@firewatch/core": "workspace:*",
"@shared/eslint": "workspace:*",
"@shared/tsconfig": "workspace:*",
"@shared/utils": "workspace:*",
"@testing/mocha": "workspace:*",
"@types/mocha": "^10.0.10"
"@types/mocha": "^10.0.10",
"@types/node": "^24.0.10"
}
}
61 changes: 61 additions & 0 deletions modules/cosmos/src/modules/ibc/account-parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Account, accountFromAny } from "@cosmjs/stargate";
import { Any } from "cosmjs-types/google/protobuf/any";
import { parseEthAccount } from "./parser";

/**
* Custom account parser that extends accountFromAny to support EthAccount format.
* This parser handles both standard Cosmos accounts and Ethermint EthAccount types.
*
* Supports the EthAccount format as defined in ethermint.types.v1:
* ```proto
* message EthAccount {
* cosmos.auth.v1beta1.BaseAccount base_account = 1;
* string code_hash = 2;
* }
* ```
* @param input The Any message containing the account.
* @returns The parsed account.
* @throws Error if parsing fails for both EthAccount and standard account formats.
*/
export function ethermintAccountParser(input: Any): Account {
try {
// Handle EthAccount specifically
if (input.typeUrl === "/ethermint.types.v1.EthAccount") {
const ethAccount = parseEthAccount(input);
if (ethAccount?.baseAccount) {
return {
address: ethAccount.baseAccount.address,
accountNumber: Number(ethAccount.baseAccount.accountNumber),
sequence: Number(ethAccount.baseAccount.sequence),
pubkey: null, // EthAccount doesn't store pubkey in the account
} as Account;
}
// If EthAccount parsing fails, fall through to standard parsing
}

// For all other account types or if EthAccount parsing failed, use standard parsing
return accountFromAny(input);
} catch (error) {
console.error("Failed to parse account with ethermintAccountParser:", error);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could define a ParserError/IBCParserError error class

// Final fallback to standard parsing, let it throw if it fails
return accountFromAny(input);
}
}

/**
* Check if an account type URL represents an EthAccount.
* @param typeUrl The type URL to check.
* @returns True if the type URL is for an EthAccount.
*/
export function isEthAccount(typeUrl: string): boolean {
return typeUrl === "/ethermint.types.v1.EthAccount";
}

/**
* Create an account parser specifically for Ethermint/Evmos chains.
* This is a factory function that returns a configured account parser.
* @returns The account parser function.
*/
export function createEthermintAccountParser() {
return (input: Any): Account => ethermintAccountParser(input);
}
Loading