Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add migration guide #102

Merged
merged 3 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
],
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[markdown]": {
"editor.formatOnSave": false
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ The authentication module is universally applied across different networks.
|---------|---------|
| **Transactions** | [@interchainjs/cosmos](/networks/cosmos/README.md) |
| **Cosmos Types** | [@interchainjs/cosmos-types](/networks/cosmos-msgs/README.md) |
| **Migration from `@cosmjs`** | [interchainjs](/networks/cosmjs/README.md) |
| **Migration from `@cosmjs`** | [Migration Guide](/docs/migration-from-cosmjs.md) |

---

Expand Down
284 changes: 284 additions & 0 deletions docs/migration-from-cosmjs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
# Migrating from CosmJS to @interchainjs/cosmos

This guide shows you how to migrate from CosmJS to the new InterchainJS SDK. The updated examples below follow the patterns used in our unit tests, with a special focus on wallet generation and signers that completely removes any CosmJS dependency.

## 1. Overview

### Goal:
Replace CosmJS with @interchainjs/cosmos to sign, build, and broadcast transactions on Cosmos-based blockchains.

### Key Improvements:
- Wallet Generation: Create wallets using our own methods (using Secp256k1Auth and Bip39) instead of CosmJS’s DirectSecp256k1HdWallet.
- Modular Imports: Import only the needed submodules to reduce bundle size.
- Unified Signer Interfaces: Use Direct (Protobuf) or Amino signing with a consistent API.


## 2. Installation

Remove CosmJS dependencies, then install the new SDK and its related packages:
``` shell
npm install @interchainjs/cosmos @interchainjs/auth @interchainjs/cosmos-types
```

## 3. Updated Wallet Generation

In the new SDK, you can generate a wallet using our own methods rather than relying on CosmJS. For example, the unit tests use:
- Secp256k1Auth.fromMnemonic – to derive authentication objects from the mnemonic.
- HDPath – to derive the correct HD paths for Cosmos.

Below is a sample code snippet illustrating the updated wallet generation:
``` typescript
// Import wallet and HD path utilities from the SDK packages
import { Secp256k1Auth } from '@interchainjs/auth/secp256k1';
import { HDPath } from '@interchainjs/types';
// Import the DirectSigner from our SDK
import { DirectSigner } from '@interchainjs/cosmos/signers/direct';
import { Bip39, Random } from '@interchainjs/crypto';
import { toEncoders } from '@interchainjs/cosmos/utils';
import { MsgSend } from 'interchainjs/cosmos/bank/v1beta1/tx';

(async () => {
// Generate a mnemonic using the SDK utility
const mnemonic = Bip39.encode(Random.getBytes(16)).toString();

// Derive authentication objects (wallet accounts) using the SDK's Secp256k1Auth
// Here we derive the first account using the standard Cosmos HD path.
const [auth] = Secp256k1Auth.fromMnemonic(mnemonic, [
HDPath.cosmos(0, 0, 0).toString(),
]);

// Prepare any encoders required for your message types
const encoders:Encoder[] = toEncoders(MsgSend);

// Define your RPC endpoint (ensure it points to a working Cosmos RPC node)
const rpcEndpoint = 'http://your-rpc-endpoint:26657';

// Create a DirectSigner instance using the auth object and your RPC endpoint.
// The options object can include chain-specific settings (like the bech32 prefix).
const signer = new DirectSigner(auth, encoders, rpcEndpoint, {
prefix: 'cosmos', // Replace with your chain's prefix if different
});

// Retrieve the wallet address from the signer
const address = await signer.getAddress();
console.log('Wallet address:', address);

// ----- Transaction Example -----
// Build your transaction message (e.g., a bank MsgSend). Refer to @interchainjs/cosmos-types for details.
const msg = {
// Example message object; adjust fields according to your chain and message type
// For instance, if using bank.MsgSend, you would populate:
typeUrl: '/cosmos.bank.v1beta1.MsgSend',
value: { fromAddress: address, toAddress: address, amount: [{ denom: 'uatom', amount: '1' }] }
};

// Sign and broadcast the transaction.
// The signAndBroadcast method handles building the transaction and sending it over RPC.
const result = await signer.signAndBroadcast([msg]);
console.log('Transaction hash:', result.hash);
})();
```
Key Points:
- No CosmJS Dependency: The wallet is generated entirely using Bip39 and Secp256k1Auth.fromMnemonic.
- HDPath Usage: The HD path is derived using HDPath.cosmos(0, 0, 0).toString(), which follows the Cosmos standard.
- DirectSigner: Instantiated with the auth object and a set of encoders (which you can populate based on your message types).


## 4. Signer Usage & Transaction Construction

### Direct Signer Usage

Using the new DirectSigner to sign and broadcast transactions now follows this pattern:

``` typescript
import { DirectSigner } from '@interchainjs/cosmos/signers/direct';
// (Wallet generation code as shown above is assumed to have been run)

// Build your transaction message (e.g., a bank message)
const msg = {
// Construct your message based on the schema from @interchainjs/cosmos-types
};

// Optionally, set fee and memo information
const fee = {
amount: [
{
denom: 'uatom',
amount: '5000',
},
],
gas: '200000',
};

// Sign and broadcast the transaction
const result = await signer.signAndBroadcast([msg], {
fee,
memo: 'migration transaction test',
});
console.log('Transaction hash:', result.hash);
```

### Amino Signer Usage

If you need Amino signing for legacy compatibility, the process is analogous:

``` typescript
import { AminoSigner } from '@interchainjs/cosmos/signers/amino';
import { toEncoders, toConverters } from '@interchainjs/cosmos/utils';
import { MsgSend } from 'interchainjs/cosmos/bank/v1beta1/tx';

(async () => {
const [auth] = Secp256k1Auth.fromMnemonic(mnemonic, [
HDPath.cosmos(0, 0, 0).toString(),
]);
const rpcEndpoint = 'http://your-rpc-endpoint:26657';

// Create an AminoSigner instance
const aminoSigner = new AminoSigner(
auth,
toEncoders(MsgSend),
toConverters(MsgSend),
rpcEndpoint,
{ prefix: 'cosmos' }
);

// Build your message and set fee/memo if needed
const msg = {
// Your message fields here
};

const fee = {
amount: [
{
denom: 'uatom',
amount: '5000',
},
],
gas: '200000',
};

const result = await aminoSigner.signAndBroadcast({
messages: [msg], fee
});
console.log('Transaction hash:', result.hash);
})();
```

## 5. CosmJS Code Comparison
To highlight the migration improvements, here is a side-by-side comparison of the previous CosmJS implementation versus the new InterchainJS approach.
### Wallet Generation
#### CosmJS Implementation:
``` typescript
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { makeCosmoshubPath } from "@cosmjs/crypto";

(async () => {
const mnemonic = "your mnemonic here";
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
hdPaths: [makeCosmoshubPath(0)],
});
const [account] = await wallet.getAccounts();
console.log("Wallet address:", account.address);
})();
```
#### InterchainJS Implementation:
``` typescript
import { Secp256k1Auth } from '@interchainjs/auth/secp256k1';
import { HDPath } from '@interchainjs/types';
import { Bip39, Random } from '@interchainjs/crypto';

(async () => {
const mnemonic = Bip39.encode(Random.getBytes(16)).toString();
const [auth] = Secp256k1Auth.fromMnemonic(mnemonic, [
HDPath.cosmos(0, 0, 0).toString(),
]);
console.log("Wallet address:", await auth.getAddress());
})();
```
### Transaction Signing and Broadcasting
#### CosmJS Implementation:
``` typescript
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { SigningStargateClient } from "@cosmjs/stargate";
import { makeCosmoshubPath } from "@cosmjs/crypto";

(async () => {
const mnemonic = "your mnemonic here";
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
hdPaths: [makeCosmoshubPath(0)],
});
const [account] = await wallet.getAccounts();
const rpcEndpoint = 'http://your-rpc-endpoint:26657';
const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet);

const msg = {
// Construct your message here
};
const fee = {
amount: [{ denom: 'uatom', amount: '5000' }],
gas: '200000',
};
const memo = "CosmJS transaction test";

const result = await client.signAndBroadcast(account.address, [msg], fee, memo);
console.log("Transaction hash:", result.transactionHash);
})();
```
#### InterchainJS Implementation:
``` typescript
import { DirectSigner } from '@interchainjs/cosmos/signers/direct';

(async () => {
// Assume wallet generation using InterchainJS methods as shown earlier has been completed.

const msg = {
// Construct your message here using @interchainjs/cosmos-types
};
const fee = {
amount: [{ denom: 'uatom', amount: '5000' }],
gas: '200000',
};
const memo = "InterchainJS transaction test";

const result = await signer.signAndBroadcast({
messages: [msg], fee, memo
});
console.log("Transaction hash:", result.hash);
})();
```

## 6. Migration Steps Summary
1. Update Dependencies:
- Remove CosmJS dependencies.
- Install @interchainjs/cosmos, @interchainjs/auth, and @interchainjs/cosmos-types.

2. Change Imports:
- Replace any CosmJS imports with the new SDK sub-module imports.
- For wallet generation, use:
``` typescript
import { Bip39, Random } from '@interchainjs/crypto';
import { Secp256k1Auth } from '@interchainjs/auth/secp256k1';
import { HDPath } from '@interchainjs/types';
```

3. Wallet Generation:
- Generate a mnemonic using Bip39 and Random
- Derive auth objects using Secp256k1Auth.fromMnemonic().
- Note: This method completely avoids any dependency on CosmJS wallet implementations.
4. Adapt Signer Interfaces:
- Use DirectSigner.fromWallet or create a new instance with your auth object.
- If needed, use AminoSigner for legacy signing.
5. Rebuild Transaction Construction:
- Replace CosmJS transaction building logic with the new SDK’s TxBuilder (accessed via signer.getTxBuilder()).
- Use message constructors and encoders from @interchainjs/cosmos-types.
6. Test Thoroughly:
- Validate transactions on testnets.
- Compare fee, gas, memo, and signature details against expected values.

## 6. Conclusion

This updated migration guide demonstrates how to generate wallets and sign transactions using the new InterchainJS SDK without any dependency on CosmJS. By leveraging built-in utilities such as Secp256k1Auth.fromMnemonic, and HDPath, your application can fully transition to a modern, modular, and lightweight approach to interacting with Cosmos blockchains.

For further details, refer to the GitHub repository README and unit tests (e.g., [token.test.ts](../networks/cosmos/starship/__tests__/token.test.ts)).

Happy migrating!
Loading