Skip to content

Commit 3ad8162

Browse files
committed
wip
1 parent f939cf2 commit 3ad8162

21 files changed

+2288
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { fromBech32, toBech32 } from "@interchainjs/encoding";
2+
import { Decimal, Uint53 } from "@interchainjs/math";
3+
import { Secp256k1HDWallet } from "@interchainjs/cosmos/wallets/secp256k1hd";
4+
import { GasPrice, SigningStargateClient, calculateFee, parseCoins, } from "@cosmjs/stargate";
5+
import type { StdFee } from "@interchainjs/cosmos";
6+
import type { MsgSend } from "interchainjs/cosmos/bank/v1beta1/tx";
7+
// ---- Types and Interfaces ----
8+
interface TransactionConfig {
9+
rpcEndpoint: string;
10+
gasPrice: string;
11+
gasLimit: number;
12+
memo?: string;
13+
}
14+
interface SendTokensParams {
15+
recipientAddress: string;
16+
amount: {
17+
denom: string;
18+
amount: string;
19+
};
20+
}
21+
// ---- Address Utilities ----
22+
export function handleBech32Address(address: string): {
23+
decodedAddress: {
24+
prefix: string;
25+
data: Uint8Array;
26+
};
27+
reEncodedAddress: string;
28+
} {
29+
const decodedAddress = fromBech32(address);
30+
const reEncodedAddress = toBech32(decodedAddress.prefix, decodedAddress.data);
31+
return {
32+
decodedAddress,
33+
reEncodedAddress,
34+
};
35+
}
36+
// ---- Coin Utilities ----
37+
export function parseCoinStrings(coinString: string) {
38+
try {
39+
const parsed = parseCoins(coinString);
40+
return {
41+
success: true,
42+
coins: parsed,
43+
total: parsed.reduce((acc, coin) => acc + Number(coin.amount), 0),
44+
};
45+
}
46+
catch (error) {
47+
return {
48+
success: false,
49+
error: `Failed to parse coin string: ${error.message}`,
50+
coins: [],
51+
total: 0,
52+
};
53+
}
54+
}
55+
// ---- Decimal Calculation Utilities ----
56+
export namespace DecimalCalculator {
57+
export function add(amount1: string, amount2: string, precision = 6): string {
58+
const dec1 = Decimal.fromUserInput(amount1, precision);
59+
const dec2 = Decimal.fromUserInput(amount2, precision);
60+
return dec1.plus(dec2).toString();
61+
}
62+
export function multiply(amount: string, multiplier: number, precision = 6): string {
63+
const dec = Decimal.fromUserInput(amount, precision);
64+
return dec.multiply(new Uint53(multiplier)).toString();
65+
}
66+
export function divide(amount: string, divisor: number, precision = 6): number {
67+
const dec = Decimal.fromUserInput(amount, precision);
68+
return dec.toFloatApproximation() / divisor;
69+
}
70+
}
71+
// ---- Transaction Management ----
72+
export class CosmosTransactionManager {
73+
private config: TransactionConfig;
74+
private signer?: DirectSecp256k1HdWallet;
75+
private client?: SigningStargateClient;
76+
constructor(config: TransactionConfig) {
77+
this.config = {
78+
...config,
79+
memo: config.memo || "Transaction via CosmJS",
80+
};
81+
}
82+
async initialize(mnemonic: string, prefix = "cosmos") {
83+
try {
84+
this.signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
85+
prefix,
86+
});
87+
this.client = await SigningClient.connectWithSigner(this.config.rpcEndpoint, this.signer, {
88+
broadcast: { checkTx: true, deliverTx: true }
89+
});
90+
return true;
91+
}
92+
catch (error) {
93+
console.error("Failed to initialize transaction manager:", error);
94+
throw new Error(`Initialization failed: ${error.message}`);
95+
}
96+
}
97+
private calculateTransactionFee(): StdFee {
98+
const gasPrice = GasPrice.fromString(this.config.gasPrice);
99+
return calculateFee(this.config.gasLimit, gasPrice);
100+
}
101+
async sendTokens(params: SendTokensParams) {
102+
if (!this.signer || !this.client) {
103+
throw new Error("Transaction manager not initialized");
104+
}
105+
try {
106+
const [account] = await this.signer.getAccounts();
107+
const senderAddress = account.address;
108+
const message: MsgSend = {
109+
fromAddress: senderAddress,
110+
toAddress: params.recipientAddress,
111+
amount: [params.amount],
112+
};
113+
const msgAny = {
114+
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
115+
value: message,
116+
};
117+
const fee = this.calculateTransactionFee();
118+
const result = await this.client.signAndBroadcast(senderAddress, [msgAny], fee, this.config.memo);
119+
return {
120+
success: true,
121+
hash: result.transactionHash,
122+
details: result,
123+
};
124+
}
125+
catch (error) {
126+
return {
127+
success: false,
128+
error: error.message,
129+
};
130+
}
131+
}
132+
}
133+
// ---- Example Usage ----
134+
async function demonstrateFeatures() {
135+
// Address handling example
136+
const addressResult = handleBech32Address("cosmos1zmj0fpkm9px3f7klg7hzycu6z6k76jskvnsc0n");
137+
console.log("Address handling result:", addressResult);
138+
// Coin parsing example
139+
const coinResult = parseCoinStrings("1000000uatom,500000stake");
140+
console.log("Coin parsing result:", coinResult);
141+
// Decimal calculations
142+
const sum = DecimalCalculator.add("123.456", "0.001");
143+
const product = DecimalCalculator.multiply("123.456", 2);
144+
const quotient = DecimalCalculator.divide("123.456", 10);
145+
console.log("Calculations:", { sum, product, quotient });
146+
// Transaction example
147+
const manager = new CosmosTransactionManager({
148+
rpcEndpoint: "rpc.cosmos.network:26657",
149+
gasPrice: "0.025uatom",
150+
gasLimit: 200000,
151+
});
152+
try {
153+
await manager.initialize("your-mnemonic-here");
154+
const result = await manager.sendTokens({
155+
recipientAddress: "cosmos1...",
156+
amount: {
157+
denom: "uatom",
158+
amount: "1000",
159+
},
160+
});
161+
console.log("Transaction result:", result);
162+
}
163+
catch (error) {
164+
console.error("Transaction failed:", error);
165+
}
166+
}
167+
// Uncomment to run all examples:
168+
// demonstrateFeatures();
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { parseCoins } from "@interchainjs/amino";
2+
import { fromBech32, toBech32 } from "@interchainjs/encoding";
3+
import { Decimal, Uint53 } from "@interchainjs/math";
4+
export function CosmjsReactTest() {
5+
return <div>CosmjsReactTest < /div>;
6+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { GasPrice, SigningClient, calculateFee } from "@interchainjs/cosmos";
2+
import { Secp256k1HDWallet } from "@interchainjs/cosmos/wallets/secp256k1hd";
3+
import type { MsgSend } from "interchainjs/cosmos/bank/v1beta1/tx";
4+
// --- Configuration & Setup ---
5+
const rpcEndpoint = "rpc.cosmos.network:26657"; // Replace with your RPC endpoint
6+
const senderMnemonic = "..."; // Replace with a valid mnemonic (for testing only!)
7+
const recipientAddress = "cosmos1..."; // Replace with a recipient address
8+
const amountToSend = {
9+
denom: "uatom",
10+
amount: "1000",
11+
};
12+
const gasPrice = GasPrice.fromString("0.025uatom");
13+
const gasLimit = 200000;
14+
const fee = calculateFee(gasLimit, gasPrice);
15+
const memo = "Sent via CosmJS";
16+
// Type registry setup (only needed for custom message types, MsgSend is built-in)
17+
// const registry = new Registry();
18+
// const typeUrl = "/cosmos.bank.v1beta1.MsgSend"; // Example type URL
19+
// registry.register(typeUrl, MsgSend);
20+
// --- Main Signing Logic (Conceptual Example) ---
21+
async function signAndBroadcast() {
22+
// 1. Get a signer (e.g., from a mnemonic or browser extension like Keplr)
23+
// Using mnemonic here for a self-contained example (DO NOT use mainnet mnemonics in code)
24+
const signer = await Secp256k1HDWallet.fromMnemonic(senderMnemonic, [
25+
{ prefix: "cosmos", hdPath: "m/44'/118'/0'/0/0" },
26+
]);
27+
const [firstAccount] = await signer.getAccounts();
28+
const senderAddress = firstAccount.address;
29+
console.log(`Sender address: ${senderAddress}`);
30+
// 2. Create the signing client
31+
const signingClient = await SigningClient.connectWithSigner(
32+
rpcEndpoint,
33+
signer,
34+
{
35+
broadcast: { checkTx: true, deliverTx: true },
36+
},
37+
);
38+
// 3. Create the message
39+
const message: MsgSend = {
40+
fromAddress: senderAddress,
41+
toAddress: recipientAddress,
42+
amount: [amountToSend],
43+
};
44+
// The type URL is crucial for Stargate messages
45+
const msgAny = {
46+
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
47+
value: message,
48+
};
49+
// 4. Sign and broadcast the transaction
50+
try {
51+
console.log("Signing and broadcasting transaction...");
52+
const result = await signingClient.signAndBroadcast(
53+
senderAddress,
54+
[msgAny],
55+
fee /* TODO: Replace with InterchainJS fee object (e.g., { amount: [{ denom, amount }], gas }) */,
56+
memo,
57+
);
58+
console.log("Transaction successful:", result.transactionHash);
59+
console.log("Result details:", result);
60+
} catch (error) {
61+
console.error("Transaction failed:", error);
62+
}
63+
}
64+
// --- Execute the function ---
65+
// signAndBroadcast(); // Uncomment to run, requires valid RPC and mnemonic
66+
console.log("Example signing code structure loaded.");
67+
console.log("Ensure RPC endpoint and mnemonic are configured before running.");
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { fromBech32, toBech32 } from "@interchainjs/encoding";
2+
import { Decimal, Uint53 } from "@interchainjs/math";
3+
import { parseCoins } from "@interchainjs/amino";
4+
// Example 1: Bech32 encoding and decoding
5+
const decodedAddress = fromBech32("cosmos1zmj0fpkm9px3f7klg7hzycu6z6k76jskvnsc0n");
6+
console.log("Decoded Address Prefix:", decodedAddress.prefix);
7+
console.log("Decoded Address Data Length:", decodedAddress.data.length);
8+
const reEncodedAddress = toBech32("cosmos", decodedAddress.data);
9+
console.log("Re-encoded Address:", reEncodedAddress);
10+
// Example 2: Parsing coin strings
11+
const coinsString = "1000000uatom,500000stake";
12+
const parsedCoins = parseCoins(coinsString);
13+
console.log("Parsed Coins:", parsedCoins);
14+
const singleCoinString = "12345uosmo";
15+
const parsedCoin = parseCoins(singleCoinString)[0];
16+
console.log("Parsed Single Coin:", parsedCoin);
17+
// Example 3: Using Decimal for calculations
18+
const amount1 = Decimal.fromUserInput("123.456", 6); // Represents 123.456000
19+
const amount2 = Decimal.fromUserInput("0.001", 6); // Represents 0.001000
20+
const sum = amount1.plus(amount2);
21+
console.log(`Sum: ${sum.toString()} (fractional digits: ${sum.fractionalDigits})`);
22+
const product = amount1.multiply(new Uint53(2)); // Multiply by 2
23+
console.log(`Product: ${product.toString()} (fractional digits: ${product.fractionalDigits})`);
24+
const division = amount1.toFloatApproximation() / 10;
25+
console.log(`Division (approx float): ${division}`);

0 commit comments

Comments
 (0)