winnode 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/chunk-J5LGTIGS.mjs +10 -0
- package/dist/chunk-J5LGTIGS.mjs.map +1 -0
- package/dist/index.d.mts +206 -0
- package/dist/index.d.ts +206 -0
- package/dist/index.js +348 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +290 -0
- package/dist/index.mjs.map +1 -0
- package/dist/keplr-N462EFWR.mjs +25 -0
- package/dist/keplr-N462EFWR.mjs.map +1 -0
- package/package.json +60 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __esm = (fn, res) => function __init() {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
};
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// lib/keplr.ts
|
|
24
|
+
var keplr_exports = {};
|
|
25
|
+
__export(keplr_exports, {
|
|
26
|
+
calculateFee: () => calculateFee
|
|
27
|
+
});
|
|
28
|
+
function pickGasPrice(chain) {
|
|
29
|
+
const feeToken = chain.fees?.fee_tokens?.[0];
|
|
30
|
+
if (!feeToken) {
|
|
31
|
+
return { denom: chain.assets?.[0]?.base || DEFAULT_DENOM, price: DEFAULT_GAS_PRICE };
|
|
32
|
+
}
|
|
33
|
+
const price = feeToken.average_gas_price ?? feeToken.low_gas_price ?? feeToken.fixed_min_gas_price ?? DEFAULT_GAS_PRICE;
|
|
34
|
+
return { denom: feeToken.denom, price };
|
|
35
|
+
}
|
|
36
|
+
async function calculateFee(chain, gasLimit) {
|
|
37
|
+
const { denom, price } = pickGasPrice(chain);
|
|
38
|
+
const amount = Math.ceil(Number(gasLimit) * price).toString();
|
|
39
|
+
return {
|
|
40
|
+
amount: [{ denom, amount }],
|
|
41
|
+
gas: gasLimit
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
var DEFAULT_GAS_PRICE, DEFAULT_DENOM;
|
|
45
|
+
var init_keplr = __esm({
|
|
46
|
+
"lib/keplr.ts"() {
|
|
47
|
+
"use strict";
|
|
48
|
+
DEFAULT_GAS_PRICE = 0.025;
|
|
49
|
+
DEFAULT_DENOM = "uatom";
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// index.ts
|
|
54
|
+
var index_exports = {};
|
|
55
|
+
__export(index_exports, {
|
|
56
|
+
cosmosTx: () => cosmos_exports,
|
|
57
|
+
evmTx: () => evm_exports,
|
|
58
|
+
isEvmChain: () => isEvmChain
|
|
59
|
+
});
|
|
60
|
+
module.exports = __toCommonJS(index_exports);
|
|
61
|
+
|
|
62
|
+
// types.ts
|
|
63
|
+
function isEvmChain(chain) {
|
|
64
|
+
const coinType = parseInt(chain.coin_type || "118");
|
|
65
|
+
return coinType === 60 || Boolean(chain.evm_rpc && chain.evm_rpc.length > 0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// cosmos/index.ts
|
|
69
|
+
var cosmos_exports = {};
|
|
70
|
+
__export(cosmos_exports, {
|
|
71
|
+
buildFee: () => buildFee,
|
|
72
|
+
clearCosmosClientCache: () => clearCosmosClientCache,
|
|
73
|
+
createCosmosRegistry: () => createCosmosRegistry,
|
|
74
|
+
delegate: () => delegate,
|
|
75
|
+
getPrimaryDenom: () => getPrimaryDenom,
|
|
76
|
+
getSigningStargateClient: () => getSigningStargateClient,
|
|
77
|
+
pickRpcEndpoint: () => pickRpcEndpoint,
|
|
78
|
+
redelegate: () => redelegate,
|
|
79
|
+
send: () => send,
|
|
80
|
+
undelegate: () => undelegate,
|
|
81
|
+
unjail: () => unjail,
|
|
82
|
+
vote: () => vote,
|
|
83
|
+
withdrawRewards: () => withdrawRewards
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// cosmos/client.ts
|
|
87
|
+
var import_stargate2 = require("@cosmjs/stargate");
|
|
88
|
+
|
|
89
|
+
// cosmos/registry.ts
|
|
90
|
+
var import_proto_signing = require("@cosmjs/proto-signing");
|
|
91
|
+
var import_stargate = require("@cosmjs/stargate");
|
|
92
|
+
var import_tx = require("cosmjs-types/cosmos/slashing/v1beta1/tx");
|
|
93
|
+
function createCosmosRegistry() {
|
|
94
|
+
return new import_proto_signing.Registry([
|
|
95
|
+
...import_stargate.defaultRegistryTypes,
|
|
96
|
+
["/cosmos.slashing.v1beta1.MsgUnjail", import_tx.MsgUnjail]
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// cosmos/fee.ts
|
|
101
|
+
function getPrimaryDenom(chain) {
|
|
102
|
+
return chain.assets?.[0]?.base || "uatom";
|
|
103
|
+
}
|
|
104
|
+
async function buildFee(chain, gasLimit) {
|
|
105
|
+
const { calculateFee: calculateFee2 } = await Promise.resolve().then(() => (init_keplr(), keplr_exports));
|
|
106
|
+
return calculateFee2(chain, gasLimit);
|
|
107
|
+
}
|
|
108
|
+
function pickRpcEndpoint(chain) {
|
|
109
|
+
const rpcList = chain.rpc || [];
|
|
110
|
+
const indexed = rpcList.find((rpc) => rpc.tx_index === "on");
|
|
111
|
+
const endpoint = (indexed || rpcList[0])?.address;
|
|
112
|
+
if (!endpoint) {
|
|
113
|
+
throw new Error(`No RPC endpoint available for chain ${chain.chain_name}`);
|
|
114
|
+
}
|
|
115
|
+
return endpoint;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// cosmos/client.ts
|
|
119
|
+
var clientCache = /* @__PURE__ */ new Map();
|
|
120
|
+
async function getSigningStargateClient(chain, signer) {
|
|
121
|
+
const rpcEndpoint = pickRpcEndpoint(chain);
|
|
122
|
+
const [account] = await signer.getAccounts();
|
|
123
|
+
const cacheKey = `${rpcEndpoint}:${account.address}`;
|
|
124
|
+
const cached = clientCache.get(cacheKey);
|
|
125
|
+
if (cached) {
|
|
126
|
+
return cached;
|
|
127
|
+
}
|
|
128
|
+
const client = await import_stargate2.SigningStargateClient.connectWithSigner(rpcEndpoint, signer, {
|
|
129
|
+
registry: createCosmosRegistry()
|
|
130
|
+
});
|
|
131
|
+
clientCache.set(cacheKey, client);
|
|
132
|
+
return client;
|
|
133
|
+
}
|
|
134
|
+
function clearCosmosClientCache() {
|
|
135
|
+
clientCache.clear();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// cosmos/tx.ts
|
|
139
|
+
async function signAndBroadcast(chain, signer, senderAddress, messages, opts, defaultGasLimit) {
|
|
140
|
+
try {
|
|
141
|
+
const gasLimit = opts.gasLimit || defaultGasLimit;
|
|
142
|
+
const client = await getSigningStargateClient(chain, signer);
|
|
143
|
+
const fee = await buildFee(chain, gasLimit);
|
|
144
|
+
const result = await client.signAndBroadcast(senderAddress, messages, fee, opts.memo || "");
|
|
145
|
+
if (result.code === 0) {
|
|
146
|
+
return { success: true, txHash: result.transactionHash, raw: result };
|
|
147
|
+
}
|
|
148
|
+
return { success: false, error: result.rawLog || `Transaction failed with code ${result.code}`, raw: result };
|
|
149
|
+
} catch (error) {
|
|
150
|
+
return { success: false, error: error?.message || "Transaction failed" };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function send(chain, signer, params, opts = {}) {
|
|
154
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
155
|
+
const message = {
|
|
156
|
+
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
|
|
157
|
+
value: {
|
|
158
|
+
fromAddress: params.fromAddress,
|
|
159
|
+
toAddress: params.toAddress,
|
|
160
|
+
amount: [{ denom, amount: params.amount }]
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
return signAndBroadcast(chain, signer, params.fromAddress, [message], opts, "200000");
|
|
164
|
+
}
|
|
165
|
+
async function delegate(chain, signer, params, opts = {}) {
|
|
166
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
167
|
+
const message = {
|
|
168
|
+
typeUrl: "/cosmos.staking.v1beta1.MsgDelegate",
|
|
169
|
+
value: {
|
|
170
|
+
delegatorAddress: params.delegatorAddress,
|
|
171
|
+
validatorAddress: params.validatorAddress,
|
|
172
|
+
amount: { denom, amount: params.amount }
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
176
|
+
}
|
|
177
|
+
async function undelegate(chain, signer, params, opts = {}) {
|
|
178
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
179
|
+
const message = {
|
|
180
|
+
typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate",
|
|
181
|
+
value: {
|
|
182
|
+
delegatorAddress: params.delegatorAddress,
|
|
183
|
+
validatorAddress: params.validatorAddress,
|
|
184
|
+
amount: { denom, amount: params.amount }
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
188
|
+
}
|
|
189
|
+
async function redelegate(chain, signer, params, opts = {}) {
|
|
190
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
191
|
+
const message = {
|
|
192
|
+
typeUrl: "/cosmos.staking.v1beta1.MsgBeginRedelegate",
|
|
193
|
+
value: {
|
|
194
|
+
delegatorAddress: params.delegatorAddress,
|
|
195
|
+
validatorSrcAddress: params.validatorSrcAddress,
|
|
196
|
+
validatorDstAddress: params.validatorDstAddress,
|
|
197
|
+
amount: { denom, amount: params.amount }
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
201
|
+
}
|
|
202
|
+
async function vote(chain, signer, params, opts = {}) {
|
|
203
|
+
const chainId = chain.chain_id || chain.chain_name;
|
|
204
|
+
const typeUrl = chainId.includes("atomone") ? "/atomone.gov.v1beta1.MsgVote" : "/cosmos.gov.v1beta1.MsgVote";
|
|
205
|
+
const message = {
|
|
206
|
+
typeUrl,
|
|
207
|
+
value: {
|
|
208
|
+
proposalId: params.proposalId,
|
|
209
|
+
voter: params.voterAddress,
|
|
210
|
+
option: params.option
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
return signAndBroadcast(chain, signer, params.voterAddress, [message], opts, "400000");
|
|
214
|
+
}
|
|
215
|
+
async function unjail(chain, signer, params, opts = {}) {
|
|
216
|
+
const message = {
|
|
217
|
+
typeUrl: "/cosmos.slashing.v1beta1.MsgUnjail",
|
|
218
|
+
value: { validatorAddr: params.validatorAddress }
|
|
219
|
+
};
|
|
220
|
+
return signAndBroadcast(chain, signer, params.senderAddress, [message], opts, "500000");
|
|
221
|
+
}
|
|
222
|
+
async function withdrawRewards(chain, signer, params, opts = {}) {
|
|
223
|
+
const message = {
|
|
224
|
+
typeUrl: "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward",
|
|
225
|
+
value: {
|
|
226
|
+
delegatorAddress: params.delegatorAddress,
|
|
227
|
+
validatorAddress: params.validatorAddress
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// evm/index.ts
|
|
234
|
+
var evm_exports = {};
|
|
235
|
+
__export(evm_exports, {
|
|
236
|
+
getBrowserSigner: () => getBrowserSigner,
|
|
237
|
+
getReadProvider: () => getReadProvider,
|
|
238
|
+
sendNative: () => sendNative,
|
|
239
|
+
sendToken: () => sendToken,
|
|
240
|
+
writeContract: () => writeContract
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// evm/tx.ts
|
|
244
|
+
var import_ethers = require("ethers");
|
|
245
|
+
var ERC20_TRANSFER_ABI = ["function transfer(address to, uint256 amount) returns (bool)"];
|
|
246
|
+
async function run(fn) {
|
|
247
|
+
try {
|
|
248
|
+
const tx = await fn();
|
|
249
|
+
const receipt = await tx.wait();
|
|
250
|
+
if (receipt && receipt.status === 0) {
|
|
251
|
+
return { success: false, error: "Transaction reverted", txHash: tx.hash, raw: receipt };
|
|
252
|
+
}
|
|
253
|
+
return { success: true, txHash: tx.hash, raw: receipt };
|
|
254
|
+
} catch (error) {
|
|
255
|
+
return { success: false, error: error?.shortMessage || error?.message || "Transaction failed" };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async function sendNative(signer, params, opts = {}) {
|
|
259
|
+
return run(
|
|
260
|
+
() => signer.sendTransaction({
|
|
261
|
+
to: params.toAddress,
|
|
262
|
+
value: (0, import_ethers.parseUnits)(params.amount, params.decimals ?? 18)
|
|
263
|
+
})
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
async function sendToken(signer, params, opts = {}) {
|
|
267
|
+
const contract = new import_ethers.Contract(params.tokenAddress, ERC20_TRANSFER_ABI, signer);
|
|
268
|
+
return run(() => contract.transfer(params.toAddress, (0, import_ethers.parseUnits)(params.amount, params.decimals ?? 18)));
|
|
269
|
+
}
|
|
270
|
+
async function writeContract(signer, contractAddress, abiFragment, method, args = [], opts = {}) {
|
|
271
|
+
const contract = new import_ethers.Contract(contractAddress, abiFragment, signer);
|
|
272
|
+
return run(() => contract[method](...args));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// evm/client.ts
|
|
276
|
+
var import_ethers2 = require("ethers");
|
|
277
|
+
|
|
278
|
+
// lib/metamask.ts
|
|
279
|
+
function isMetaMaskInstalled() {
|
|
280
|
+
return typeof window !== "undefined" && Boolean(window.ethereum);
|
|
281
|
+
}
|
|
282
|
+
function getMetaMask() {
|
|
283
|
+
if (!isMetaMaskInstalled()) {
|
|
284
|
+
throw new Error("MetaMask extension is not installed");
|
|
285
|
+
}
|
|
286
|
+
return window.ethereum;
|
|
287
|
+
}
|
|
288
|
+
function toHexChainId(chain) {
|
|
289
|
+
if (!chain.evm_chain_id) {
|
|
290
|
+
throw new Error(`No evm_chain_id configured for chain ${chain.chain_name}`);
|
|
291
|
+
}
|
|
292
|
+
return `0x${chain.evm_chain_id.toString(16)}`;
|
|
293
|
+
}
|
|
294
|
+
async function switchEthereumChain(chain) {
|
|
295
|
+
const ethereum = getMetaMask();
|
|
296
|
+
const chainIdHex = toHexChainId(chain);
|
|
297
|
+
try {
|
|
298
|
+
await ethereum.request({
|
|
299
|
+
method: "wallet_switchEthereumChain",
|
|
300
|
+
params: [{ chainId: chainIdHex }]
|
|
301
|
+
});
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (error?.code !== 4902) {
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
const asset = chain.assets?.[0];
|
|
307
|
+
await ethereum.request({
|
|
308
|
+
method: "wallet_addEthereumChain",
|
|
309
|
+
params: [
|
|
310
|
+
{
|
|
311
|
+
chainId: chainIdHex,
|
|
312
|
+
chainName: chain.chain_name,
|
|
313
|
+
nativeCurrency: {
|
|
314
|
+
name: asset?.display || asset?.base || chain.chain_name,
|
|
315
|
+
symbol: asset?.symbol || asset?.display || "ETH",
|
|
316
|
+
decimals: 18
|
|
317
|
+
},
|
|
318
|
+
rpcUrls: (chain.evm_rpc || []).map((rpc) => rpc.address)
|
|
319
|
+
}
|
|
320
|
+
]
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// evm/client.ts
|
|
326
|
+
function getReadProvider(chain) {
|
|
327
|
+
const endpoint = chain.evm_rpc?.[0]?.address || chain.rpc?.[0]?.address;
|
|
328
|
+
if (!endpoint) {
|
|
329
|
+
throw new Error(`No EVM RPC endpoint available for chain ${chain.chain_name}`);
|
|
330
|
+
}
|
|
331
|
+
return new import_ethers2.JsonRpcProvider(endpoint);
|
|
332
|
+
}
|
|
333
|
+
async function getBrowserSigner(chain) {
|
|
334
|
+
if (!isMetaMaskInstalled()) {
|
|
335
|
+
throw new Error("MetaMask extension is not installed");
|
|
336
|
+
}
|
|
337
|
+
await switchEthereumChain(chain);
|
|
338
|
+
const ethereum = getMetaMask();
|
|
339
|
+
const provider = new import_ethers2.BrowserProvider(ethereum);
|
|
340
|
+
return provider.getSigner();
|
|
341
|
+
}
|
|
342
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
343
|
+
0 && (module.exports = {
|
|
344
|
+
cosmosTx,
|
|
345
|
+
evmTx,
|
|
346
|
+
isEvmChain
|
|
347
|
+
});
|
|
348
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../lib/keplr.ts","../index.ts","../types.ts","../cosmos/index.ts","../cosmos/client.ts","../cosmos/registry.ts","../cosmos/fee.ts","../cosmos/tx.ts","../evm/index.ts","../evm/tx.ts","../evm/client.ts","../lib/metamask.ts"],"sourcesContent":["import { ChainData } from '../types/chain';\n\nconst DEFAULT_GAS_PRICE = 0.025;\nconst DEFAULT_DENOM = 'uatom';\n\n/**\n * Picks a gas price for the chain's primary fee token, preferring the\n * average price, then the low price, then the fixed minimum, and finally\n * falling back to a conservative default for chains that don't publish\n * fee_tokens (e.g. local devnets).\n */\nfunction pickGasPrice(chain: ChainData): { denom: string; price: number } {\n const feeToken = chain.fees?.fee_tokens?.[0];\n if (!feeToken) {\n return { denom: chain.assets?.[0]?.base || DEFAULT_DENOM, price: DEFAULT_GAS_PRICE };\n }\n\n const price =\n feeToken.average_gas_price ?? feeToken.low_gas_price ?? feeToken.fixed_min_gas_price ?? DEFAULT_GAS_PRICE;\n\n return { denom: feeToken.denom, price };\n}\n\nexport async function calculateFee(\n chain: ChainData,\n gasLimit: string\n): Promise<{ amount: Array<{ denom: string; amount: string }>; gas: string }> {\n const { denom, price } = pickGasPrice(chain);\n const amount = Math.ceil(Number(gasLimit) * price).toString();\n\n return {\n amount: [{ denom, amount }],\n gas: gasLimit,\n };\n}\n","/**\n * WinScan Tx SDK\n *\n * Two independent, chain-type-specific transaction toolkits:\n * - `sdk/cosmos` — send, delegate, undelegate, redelegate, vote, unjail,\n * withdrawRewards for Cosmos SDK chains (signs via any OfflineSigner:\n * Keplr, Leap, etc).\n * - `sdk/evm` — sendNative, sendToken, writeContract for EVM chains\n * (signs via the injected browser wallet, e.g. MetaMask).\n *\n * Use `isEvmChain(chain)` to pick which one applies to a given chain config.\n */\nexport { isEvmChain } from './types';\nexport type { TxResult, TxOptions } from './types';\n\nexport * as cosmosTx from './cosmos';\nexport * as evmTx from './evm';\n","import { ChainData } from './types/chain';\n\nexport interface TxResult {\n success: boolean;\n txHash?: string;\n error?: string;\n raw?: any;\n}\n\nexport interface TxOptions {\n memo?: string;\n gasLimit?: string;\n}\n\n/**\n * A chain is treated as EVM when it declares evm_rpc endpoints or its\n * coin_type is 60 (Ethereum's SLIP-44 index) — same heuristic used across\n * the rest of the app (see lib/keplr.ts isEvmChain checks).\n */\nexport function isEvmChain(chain: ChainData): boolean {\n const coinType = parseInt(chain.coin_type || '118');\n return coinType === 60 || Boolean(chain.evm_rpc && chain.evm_rpc.length > 0);\n}\n","export * from './tx';\nexport { getSigningStargateClient, clearCosmosClientCache } from './client';\nexport { createCosmosRegistry } from './registry';\nexport { getPrimaryDenom, pickRpcEndpoint, buildFee } from './fee';\n","import { SigningStargateClient } from '@cosmjs/stargate';\nimport type { OfflineSigner } from '@cosmjs/proto-signing';\nimport { ChainData } from '../types/chain';\nimport { createCosmosRegistry } from './registry';\nimport { pickRpcEndpoint } from './fee';\n\nconst clientCache = new Map<string, SigningStargateClient>();\n\n/**\n * Connects a SigningStargateClient for the given chain using any\n * OfflineSigner-compatible wallet (Keplr's getOfflineSignerAuto/getOfflineSigner,\n * Leap, etc). Clients are cached per rpc+address so repeated calls in the\n * same session reuse the open connection.\n */\nexport async function getSigningStargateClient(\n chain: ChainData,\n signer: OfflineSigner\n): Promise<SigningStargateClient> {\n const rpcEndpoint = pickRpcEndpoint(chain);\n const [account] = await signer.getAccounts();\n const cacheKey = `${rpcEndpoint}:${account.address}`;\n\n const cached = clientCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n // @cosmjs/proto-signing is duplicated (top-level ^0.37 vs stargate's\n // nested ^0.38), so Registry's type identity differs even though the\n // runtime shape is compatible. Same workaround used in lib/keplr.ts.\n const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, signer, {\n registry: createCosmosRegistry() as any,\n });\n\n clientCache.set(cacheKey, client);\n return client;\n}\n\nexport function clearCosmosClientCache(): void {\n clientCache.clear();\n}\n","import { Registry } from '@cosmjs/proto-signing';\nimport { defaultRegistryTypes } from '@cosmjs/stargate';\nimport { MsgUnjail } from 'cosmjs-types/cosmos/slashing/v1beta1/tx';\n\n/**\n * @cosmjs/stargate's defaultRegistryTypes already covers MsgSend, MsgDelegate,\n * MsgUndelegate, MsgBeginRedelegate, MsgVote and MsgWithdrawDelegatorReward.\n * MsgUnjail is the only staking-adjacent message missing from it.\n */\nexport function createCosmosRegistry(): Registry {\n return new Registry([\n ...defaultRegistryTypes,\n ['/cosmos.slashing.v1beta1.MsgUnjail', MsgUnjail],\n ] as any);\n}\n","import { ChainData } from '../types/chain';\n\nexport function getPrimaryDenom(chain: ChainData): string {\n return chain.assets?.[0]?.base || 'uatom';\n}\n\n/**\n * Delegates to the app's existing, battle-tested fee calculation\n * (gas_price / fee_tokens / exponent-based fallbacks, PaxiHub minimums, etc.)\n * so every SDK tx uses the same fee logic as the rest of the explorer.\n */\nexport async function buildFee(\n chain: ChainData,\n gasLimit: string\n): Promise<{ amount: Array<{ denom: string; amount: string }>; gas: string }> {\n const { calculateFee } = await import('../lib/keplr');\n return calculateFee(chain, gasLimit);\n}\n\n/**\n * Picks the RPC endpoint with tx_index enabled when available, otherwise\n * falls back to the first configured endpoint.\n */\nexport function pickRpcEndpoint(chain: ChainData): string {\n const rpcList = chain.rpc || [];\n const indexed = rpcList.find((rpc) => rpc.tx_index === 'on');\n const endpoint = (indexed || rpcList[0])?.address;\n\n if (!endpoint) {\n throw new Error(`No RPC endpoint available for chain ${chain.chain_name}`);\n }\n\n return endpoint;\n}\n","import type { OfflineSigner } from '@cosmjs/proto-signing';\nimport { ChainData } from '../types/chain';\nimport { TxOptions, TxResult } from '../types';\nimport { getSigningStargateClient } from './client';\nimport { buildFee, getPrimaryDenom } from './fee';\n\nexport interface SendParams {\n fromAddress: string;\n toAddress: string;\n amount: string;\n denom?: string;\n}\n\nexport interface DelegateParams {\n delegatorAddress: string;\n validatorAddress: string;\n amount: string;\n denom?: string;\n}\n\nexport interface UndelegateParams extends DelegateParams {}\n\nexport interface RedelegateParams {\n delegatorAddress: string;\n validatorSrcAddress: string;\n validatorDstAddress: string;\n amount: string;\n denom?: string;\n}\n\n/** 1 = Yes, 2 = Abstain, 3 = No, 4 = NoWithVeto */\nexport type VoteOption = 1 | 2 | 3 | 4;\n\nexport interface VoteParams {\n voterAddress: string;\n proposalId: string;\n option: VoteOption;\n}\n\nexport interface UnjailParams {\n senderAddress: string;\n validatorAddress: string;\n}\n\nexport interface WithdrawRewardsParams {\n delegatorAddress: string;\n validatorAddress: string;\n}\n\nasync function signAndBroadcast(\n chain: ChainData,\n signer: OfflineSigner,\n senderAddress: string,\n messages: Array<{ typeUrl: string; value: any }>,\n opts: TxOptions,\n defaultGasLimit: string\n): Promise<TxResult> {\n try {\n const gasLimit = opts.gasLimit || defaultGasLimit;\n const client = await getSigningStargateClient(chain, signer);\n const fee = await buildFee(chain, gasLimit);\n\n const result = await client.signAndBroadcast(senderAddress, messages, fee, opts.memo || '');\n\n if (result.code === 0) {\n return { success: true, txHash: result.transactionHash, raw: result };\n }\n return { success: false, error: result.rawLog || `Transaction failed with code ${result.code}`, raw: result };\n } catch (error: any) {\n return { success: false, error: error?.message || 'Transaction failed' };\n }\n}\n\nexport async function send(\n chain: ChainData,\n signer: OfflineSigner,\n params: SendParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const denom = params.denom || getPrimaryDenom(chain);\n const message = {\n typeUrl: '/cosmos.bank.v1beta1.MsgSend',\n value: {\n fromAddress: params.fromAddress,\n toAddress: params.toAddress,\n amount: [{ denom, amount: params.amount }],\n },\n };\n return signAndBroadcast(chain, signer, params.fromAddress, [message], opts, '200000');\n}\n\nexport async function delegate(\n chain: ChainData,\n signer: OfflineSigner,\n params: DelegateParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const denom = params.denom || getPrimaryDenom(chain);\n const message = {\n typeUrl: '/cosmos.staking.v1beta1.MsgDelegate',\n value: {\n delegatorAddress: params.delegatorAddress,\n validatorAddress: params.validatorAddress,\n amount: { denom, amount: params.amount },\n },\n };\n return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, '300000');\n}\n\nexport async function undelegate(\n chain: ChainData,\n signer: OfflineSigner,\n params: UndelegateParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const denom = params.denom || getPrimaryDenom(chain);\n const message = {\n typeUrl: '/cosmos.staking.v1beta1.MsgUndelegate',\n value: {\n delegatorAddress: params.delegatorAddress,\n validatorAddress: params.validatorAddress,\n amount: { denom, amount: params.amount },\n },\n };\n return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, '300000');\n}\n\nexport async function redelegate(\n chain: ChainData,\n signer: OfflineSigner,\n params: RedelegateParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const denom = params.denom || getPrimaryDenom(chain);\n const message = {\n typeUrl: '/cosmos.staking.v1beta1.MsgBeginRedelegate',\n value: {\n delegatorAddress: params.delegatorAddress,\n validatorSrcAddress: params.validatorSrcAddress,\n validatorDstAddress: params.validatorDstAddress,\n amount: { denom, amount: params.amount },\n },\n };\n return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, '300000');\n}\n\nexport async function vote(\n chain: ChainData,\n signer: OfflineSigner,\n params: VoteParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const chainId = chain.chain_id || chain.chain_name;\n const typeUrl = chainId.includes('atomone') ? '/atomone.gov.v1beta1.MsgVote' : '/cosmos.gov.v1beta1.MsgVote';\n const message = {\n typeUrl,\n value: {\n proposalId: params.proposalId,\n voter: params.voterAddress,\n option: params.option,\n },\n };\n return signAndBroadcast(chain, signer, params.voterAddress, [message], opts, '400000');\n}\n\nexport async function unjail(\n chain: ChainData,\n signer: OfflineSigner,\n params: UnjailParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const message = {\n typeUrl: '/cosmos.slashing.v1beta1.MsgUnjail',\n value: { validatorAddr: params.validatorAddress },\n };\n return signAndBroadcast(chain, signer, params.senderAddress, [message], opts, '500000');\n}\n\nexport async function withdrawRewards(\n chain: ChainData,\n signer: OfflineSigner,\n params: WithdrawRewardsParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const message = {\n typeUrl: '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward',\n value: {\n delegatorAddress: params.delegatorAddress,\n validatorAddress: params.validatorAddress,\n },\n };\n return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, '300000');\n}\n","export * from './tx';\nexport { getReadProvider, getBrowserSigner } from './client';\n","import { Contract, parseUnits, JsonRpcSigner } from 'ethers';\nimport { TxOptions, TxResult } from '../types';\n\nexport interface SendNativeParams {\n toAddress: string;\n amount: string; // human-readable, e.g. \"1.5\"\n decimals?: number; // defaults to 18\n}\n\nexport interface SendTokenParams {\n tokenAddress: string;\n toAddress: string;\n amount: string; // human-readable\n decimals?: number; // defaults to 18\n}\n\nconst ERC20_TRANSFER_ABI = ['function transfer(address to, uint256 amount) returns (bool)'];\n\nasync function run(fn: () => Promise<{ hash: string; wait: () => Promise<any> }>): Promise<TxResult> {\n try {\n const tx = await fn();\n const receipt = await tx.wait();\n if (receipt && receipt.status === 0) {\n return { success: false, error: 'Transaction reverted', txHash: tx.hash, raw: receipt };\n }\n return { success: true, txHash: tx.hash, raw: receipt };\n } catch (error: any) {\n return { success: false, error: error?.shortMessage || error?.message || 'Transaction failed' };\n }\n}\n\n/** Sends the chain's native coin (e.g. MON on Monad). */\nexport async function sendNative(\n signer: JsonRpcSigner,\n params: SendNativeParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n return run(() =>\n signer.sendTransaction({\n to: params.toAddress,\n value: parseUnits(params.amount, params.decimals ?? 18),\n })\n );\n}\n\n/** Sends an ERC-20 token via its standard `transfer` method. */\nexport async function sendToken(\n signer: JsonRpcSigner,\n params: SendTokenParams,\n opts: TxOptions = {}\n): Promise<TxResult> {\n const contract = new Contract(params.tokenAddress, ERC20_TRANSFER_ABI, signer);\n return run(() => contract.transfer(params.toAddress, parseUnits(params.amount, params.decimals ?? 18)));\n}\n\n/**\n * Generic contract write, for chains that expose staking/governance actions\n * (delegate, undelegate, vote, unjail) through a contract or precompile\n * rather than a native Cosmos message — e.g. Cosmos-EVM staking/gov\n * precompiles. Pass the ABI fragment for the single method being called.\n */\nexport async function writeContract(\n signer: JsonRpcSigner,\n contractAddress: string,\n abiFragment: string[],\n method: string,\n args: any[] = [],\n opts: TxOptions = {}\n): Promise<TxResult> {\n const contract = new Contract(contractAddress, abiFragment, signer);\n return run(() => contract[method](...args));\n}\n","import { BrowserProvider, JsonRpcProvider, JsonRpcSigner } from 'ethers';\nimport { ChainData } from '../types/chain';\nimport { getMetaMask, isMetaMaskInstalled, switchEthereumChain } from '../lib/metamask';\n\n/**\n * Read-only provider for the chain's EVM RPC (falls back to the Tendermint\n * rpc list for chains that only expose one endpoint set).\n */\nexport function getReadProvider(chain: ChainData): JsonRpcProvider {\n const endpoint = chain.evm_rpc?.[0]?.address || chain.rpc?.[0]?.address;\n if (!endpoint) {\n throw new Error(`No EVM RPC endpoint available for chain ${chain.chain_name}`);\n }\n return new JsonRpcProvider(endpoint);\n}\n\n/**\n * Signer backed by the injected wallet (MetaMask). Ensures the wallet is\n * switched to the requested chain before returning the signer.\n */\nexport async function getBrowserSigner(chain: ChainData): Promise<JsonRpcSigner> {\n if (!isMetaMaskInstalled()) {\n throw new Error('MetaMask extension is not installed');\n }\n\n await switchEthereumChain(chain);\n\n const ethereum = getMetaMask();\n const provider = new BrowserProvider(ethereum);\n return provider.getSigner();\n}\n","import { ChainData } from '../types/chain';\n\ninterface Eip1193Provider {\n request: (args: { method: string; params?: any[] }) => Promise<any>;\n}\n\ndeclare global {\n interface Window {\n ethereum?: Eip1193Provider;\n }\n}\n\nexport function isMetaMaskInstalled(): boolean {\n return typeof window !== 'undefined' && Boolean(window.ethereum);\n}\n\nexport function getMetaMask(): Eip1193Provider {\n if (!isMetaMaskInstalled()) {\n throw new Error('MetaMask extension is not installed');\n }\n return window.ethereum as Eip1193Provider;\n}\n\nfunction toHexChainId(chain: ChainData): string {\n if (!chain.evm_chain_id) {\n throw new Error(`No evm_chain_id configured for chain ${chain.chain_name}`);\n }\n return `0x${chain.evm_chain_id.toString(16)}`;\n}\n\n/**\n * Switches the wallet's active chain, adding it first if MetaMask doesn't\n * already know about it (error code 4902).\n */\nexport async function switchEthereumChain(chain: ChainData): Promise<void> {\n const ethereum = getMetaMask();\n const chainIdHex = toHexChainId(chain);\n\n try {\n await ethereum.request({\n method: 'wallet_switchEthereumChain',\n params: [{ chainId: chainIdHex }],\n });\n } catch (error: any) {\n if (error?.code !== 4902) {\n throw error;\n }\n\n const asset = chain.assets?.[0];\n await ethereum.request({\n method: 'wallet_addEthereumChain',\n params: [\n {\n chainId: chainIdHex,\n chainName: chain.chain_name,\n nativeCurrency: {\n name: asset?.display || asset?.base || chain.chain_name,\n symbol: asset?.symbol || asset?.display || 'ETH',\n decimals: 18,\n },\n rpcUrls: (chain.evm_rpc || []).map((rpc) => rpc.address),\n },\n ],\n });\n }\n}\n"],"mappings":"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","names":["import_stargate","calculateFee","import_ethers"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-J5LGTIGS.mjs";
|
|
4
|
+
|
|
5
|
+
// types.ts
|
|
6
|
+
function isEvmChain(chain) {
|
|
7
|
+
const coinType = parseInt(chain.coin_type || "118");
|
|
8
|
+
return coinType === 60 || Boolean(chain.evm_rpc && chain.evm_rpc.length > 0);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// cosmos/index.ts
|
|
12
|
+
var cosmos_exports = {};
|
|
13
|
+
__export(cosmos_exports, {
|
|
14
|
+
buildFee: () => buildFee,
|
|
15
|
+
clearCosmosClientCache: () => clearCosmosClientCache,
|
|
16
|
+
createCosmosRegistry: () => createCosmosRegistry,
|
|
17
|
+
delegate: () => delegate,
|
|
18
|
+
getPrimaryDenom: () => getPrimaryDenom,
|
|
19
|
+
getSigningStargateClient: () => getSigningStargateClient,
|
|
20
|
+
pickRpcEndpoint: () => pickRpcEndpoint,
|
|
21
|
+
redelegate: () => redelegate,
|
|
22
|
+
send: () => send,
|
|
23
|
+
undelegate: () => undelegate,
|
|
24
|
+
unjail: () => unjail,
|
|
25
|
+
vote: () => vote,
|
|
26
|
+
withdrawRewards: () => withdrawRewards
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// cosmos/client.ts
|
|
30
|
+
import { SigningStargateClient } from "@cosmjs/stargate";
|
|
31
|
+
|
|
32
|
+
// cosmos/registry.ts
|
|
33
|
+
import { Registry } from "@cosmjs/proto-signing";
|
|
34
|
+
import { defaultRegistryTypes } from "@cosmjs/stargate";
|
|
35
|
+
import { MsgUnjail } from "cosmjs-types/cosmos/slashing/v1beta1/tx";
|
|
36
|
+
function createCosmosRegistry() {
|
|
37
|
+
return new Registry([
|
|
38
|
+
...defaultRegistryTypes,
|
|
39
|
+
["/cosmos.slashing.v1beta1.MsgUnjail", MsgUnjail]
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// cosmos/fee.ts
|
|
44
|
+
function getPrimaryDenom(chain) {
|
|
45
|
+
return chain.assets?.[0]?.base || "uatom";
|
|
46
|
+
}
|
|
47
|
+
async function buildFee(chain, gasLimit) {
|
|
48
|
+
const { calculateFee } = await import("./keplr-N462EFWR.mjs");
|
|
49
|
+
return calculateFee(chain, gasLimit);
|
|
50
|
+
}
|
|
51
|
+
function pickRpcEndpoint(chain) {
|
|
52
|
+
const rpcList = chain.rpc || [];
|
|
53
|
+
const indexed = rpcList.find((rpc) => rpc.tx_index === "on");
|
|
54
|
+
const endpoint = (indexed || rpcList[0])?.address;
|
|
55
|
+
if (!endpoint) {
|
|
56
|
+
throw new Error(`No RPC endpoint available for chain ${chain.chain_name}`);
|
|
57
|
+
}
|
|
58
|
+
return endpoint;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// cosmos/client.ts
|
|
62
|
+
var clientCache = /* @__PURE__ */ new Map();
|
|
63
|
+
async function getSigningStargateClient(chain, signer) {
|
|
64
|
+
const rpcEndpoint = pickRpcEndpoint(chain);
|
|
65
|
+
const [account] = await signer.getAccounts();
|
|
66
|
+
const cacheKey = `${rpcEndpoint}:${account.address}`;
|
|
67
|
+
const cached = clientCache.get(cacheKey);
|
|
68
|
+
if (cached) {
|
|
69
|
+
return cached;
|
|
70
|
+
}
|
|
71
|
+
const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, signer, {
|
|
72
|
+
registry: createCosmosRegistry()
|
|
73
|
+
});
|
|
74
|
+
clientCache.set(cacheKey, client);
|
|
75
|
+
return client;
|
|
76
|
+
}
|
|
77
|
+
function clearCosmosClientCache() {
|
|
78
|
+
clientCache.clear();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// cosmos/tx.ts
|
|
82
|
+
async function signAndBroadcast(chain, signer, senderAddress, messages, opts, defaultGasLimit) {
|
|
83
|
+
try {
|
|
84
|
+
const gasLimit = opts.gasLimit || defaultGasLimit;
|
|
85
|
+
const client = await getSigningStargateClient(chain, signer);
|
|
86
|
+
const fee = await buildFee(chain, gasLimit);
|
|
87
|
+
const result = await client.signAndBroadcast(senderAddress, messages, fee, opts.memo || "");
|
|
88
|
+
if (result.code === 0) {
|
|
89
|
+
return { success: true, txHash: result.transactionHash, raw: result };
|
|
90
|
+
}
|
|
91
|
+
return { success: false, error: result.rawLog || `Transaction failed with code ${result.code}`, raw: result };
|
|
92
|
+
} catch (error) {
|
|
93
|
+
return { success: false, error: error?.message || "Transaction failed" };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function send(chain, signer, params, opts = {}) {
|
|
97
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
98
|
+
const message = {
|
|
99
|
+
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
|
|
100
|
+
value: {
|
|
101
|
+
fromAddress: params.fromAddress,
|
|
102
|
+
toAddress: params.toAddress,
|
|
103
|
+
amount: [{ denom, amount: params.amount }]
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return signAndBroadcast(chain, signer, params.fromAddress, [message], opts, "200000");
|
|
107
|
+
}
|
|
108
|
+
async function delegate(chain, signer, params, opts = {}) {
|
|
109
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
110
|
+
const message = {
|
|
111
|
+
typeUrl: "/cosmos.staking.v1beta1.MsgDelegate",
|
|
112
|
+
value: {
|
|
113
|
+
delegatorAddress: params.delegatorAddress,
|
|
114
|
+
validatorAddress: params.validatorAddress,
|
|
115
|
+
amount: { denom, amount: params.amount }
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
119
|
+
}
|
|
120
|
+
async function undelegate(chain, signer, params, opts = {}) {
|
|
121
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
122
|
+
const message = {
|
|
123
|
+
typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate",
|
|
124
|
+
value: {
|
|
125
|
+
delegatorAddress: params.delegatorAddress,
|
|
126
|
+
validatorAddress: params.validatorAddress,
|
|
127
|
+
amount: { denom, amount: params.amount }
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
131
|
+
}
|
|
132
|
+
async function redelegate(chain, signer, params, opts = {}) {
|
|
133
|
+
const denom = params.denom || getPrimaryDenom(chain);
|
|
134
|
+
const message = {
|
|
135
|
+
typeUrl: "/cosmos.staking.v1beta1.MsgBeginRedelegate",
|
|
136
|
+
value: {
|
|
137
|
+
delegatorAddress: params.delegatorAddress,
|
|
138
|
+
validatorSrcAddress: params.validatorSrcAddress,
|
|
139
|
+
validatorDstAddress: params.validatorDstAddress,
|
|
140
|
+
amount: { denom, amount: params.amount }
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
144
|
+
}
|
|
145
|
+
async function vote(chain, signer, params, opts = {}) {
|
|
146
|
+
const chainId = chain.chain_id || chain.chain_name;
|
|
147
|
+
const typeUrl = chainId.includes("atomone") ? "/atomone.gov.v1beta1.MsgVote" : "/cosmos.gov.v1beta1.MsgVote";
|
|
148
|
+
const message = {
|
|
149
|
+
typeUrl,
|
|
150
|
+
value: {
|
|
151
|
+
proposalId: params.proposalId,
|
|
152
|
+
voter: params.voterAddress,
|
|
153
|
+
option: params.option
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
return signAndBroadcast(chain, signer, params.voterAddress, [message], opts, "400000");
|
|
157
|
+
}
|
|
158
|
+
async function unjail(chain, signer, params, opts = {}) {
|
|
159
|
+
const message = {
|
|
160
|
+
typeUrl: "/cosmos.slashing.v1beta1.MsgUnjail",
|
|
161
|
+
value: { validatorAddr: params.validatorAddress }
|
|
162
|
+
};
|
|
163
|
+
return signAndBroadcast(chain, signer, params.senderAddress, [message], opts, "500000");
|
|
164
|
+
}
|
|
165
|
+
async function withdrawRewards(chain, signer, params, opts = {}) {
|
|
166
|
+
const message = {
|
|
167
|
+
typeUrl: "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward",
|
|
168
|
+
value: {
|
|
169
|
+
delegatorAddress: params.delegatorAddress,
|
|
170
|
+
validatorAddress: params.validatorAddress
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
return signAndBroadcast(chain, signer, params.delegatorAddress, [message], opts, "300000");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// evm/index.ts
|
|
177
|
+
var evm_exports = {};
|
|
178
|
+
__export(evm_exports, {
|
|
179
|
+
getBrowserSigner: () => getBrowserSigner,
|
|
180
|
+
getReadProvider: () => getReadProvider,
|
|
181
|
+
sendNative: () => sendNative,
|
|
182
|
+
sendToken: () => sendToken,
|
|
183
|
+
writeContract: () => writeContract
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// evm/tx.ts
|
|
187
|
+
import { Contract, parseUnits } from "ethers";
|
|
188
|
+
var ERC20_TRANSFER_ABI = ["function transfer(address to, uint256 amount) returns (bool)"];
|
|
189
|
+
async function run(fn) {
|
|
190
|
+
try {
|
|
191
|
+
const tx = await fn();
|
|
192
|
+
const receipt = await tx.wait();
|
|
193
|
+
if (receipt && receipt.status === 0) {
|
|
194
|
+
return { success: false, error: "Transaction reverted", txHash: tx.hash, raw: receipt };
|
|
195
|
+
}
|
|
196
|
+
return { success: true, txHash: tx.hash, raw: receipt };
|
|
197
|
+
} catch (error) {
|
|
198
|
+
return { success: false, error: error?.shortMessage || error?.message || "Transaction failed" };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async function sendNative(signer, params, opts = {}) {
|
|
202
|
+
return run(
|
|
203
|
+
() => signer.sendTransaction({
|
|
204
|
+
to: params.toAddress,
|
|
205
|
+
value: parseUnits(params.amount, params.decimals ?? 18)
|
|
206
|
+
})
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
async function sendToken(signer, params, opts = {}) {
|
|
210
|
+
const contract = new Contract(params.tokenAddress, ERC20_TRANSFER_ABI, signer);
|
|
211
|
+
return run(() => contract.transfer(params.toAddress, parseUnits(params.amount, params.decimals ?? 18)));
|
|
212
|
+
}
|
|
213
|
+
async function writeContract(signer, contractAddress, abiFragment, method, args = [], opts = {}) {
|
|
214
|
+
const contract = new Contract(contractAddress, abiFragment, signer);
|
|
215
|
+
return run(() => contract[method](...args));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// evm/client.ts
|
|
219
|
+
import { BrowserProvider, JsonRpcProvider } from "ethers";
|
|
220
|
+
|
|
221
|
+
// lib/metamask.ts
|
|
222
|
+
function isMetaMaskInstalled() {
|
|
223
|
+
return typeof window !== "undefined" && Boolean(window.ethereum);
|
|
224
|
+
}
|
|
225
|
+
function getMetaMask() {
|
|
226
|
+
if (!isMetaMaskInstalled()) {
|
|
227
|
+
throw new Error("MetaMask extension is not installed");
|
|
228
|
+
}
|
|
229
|
+
return window.ethereum;
|
|
230
|
+
}
|
|
231
|
+
function toHexChainId(chain) {
|
|
232
|
+
if (!chain.evm_chain_id) {
|
|
233
|
+
throw new Error(`No evm_chain_id configured for chain ${chain.chain_name}`);
|
|
234
|
+
}
|
|
235
|
+
return `0x${chain.evm_chain_id.toString(16)}`;
|
|
236
|
+
}
|
|
237
|
+
async function switchEthereumChain(chain) {
|
|
238
|
+
const ethereum = getMetaMask();
|
|
239
|
+
const chainIdHex = toHexChainId(chain);
|
|
240
|
+
try {
|
|
241
|
+
await ethereum.request({
|
|
242
|
+
method: "wallet_switchEthereumChain",
|
|
243
|
+
params: [{ chainId: chainIdHex }]
|
|
244
|
+
});
|
|
245
|
+
} catch (error) {
|
|
246
|
+
if (error?.code !== 4902) {
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
const asset = chain.assets?.[0];
|
|
250
|
+
await ethereum.request({
|
|
251
|
+
method: "wallet_addEthereumChain",
|
|
252
|
+
params: [
|
|
253
|
+
{
|
|
254
|
+
chainId: chainIdHex,
|
|
255
|
+
chainName: chain.chain_name,
|
|
256
|
+
nativeCurrency: {
|
|
257
|
+
name: asset?.display || asset?.base || chain.chain_name,
|
|
258
|
+
symbol: asset?.symbol || asset?.display || "ETH",
|
|
259
|
+
decimals: 18
|
|
260
|
+
},
|
|
261
|
+
rpcUrls: (chain.evm_rpc || []).map((rpc) => rpc.address)
|
|
262
|
+
}
|
|
263
|
+
]
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// evm/client.ts
|
|
269
|
+
function getReadProvider(chain) {
|
|
270
|
+
const endpoint = chain.evm_rpc?.[0]?.address || chain.rpc?.[0]?.address;
|
|
271
|
+
if (!endpoint) {
|
|
272
|
+
throw new Error(`No EVM RPC endpoint available for chain ${chain.chain_name}`);
|
|
273
|
+
}
|
|
274
|
+
return new JsonRpcProvider(endpoint);
|
|
275
|
+
}
|
|
276
|
+
async function getBrowserSigner(chain) {
|
|
277
|
+
if (!isMetaMaskInstalled()) {
|
|
278
|
+
throw new Error("MetaMask extension is not installed");
|
|
279
|
+
}
|
|
280
|
+
await switchEthereumChain(chain);
|
|
281
|
+
const ethereum = getMetaMask();
|
|
282
|
+
const provider = new BrowserProvider(ethereum);
|
|
283
|
+
return provider.getSigner();
|
|
284
|
+
}
|
|
285
|
+
export {
|
|
286
|
+
cosmos_exports as cosmosTx,
|
|
287
|
+
evm_exports as evmTx,
|
|
288
|
+
isEvmChain
|
|
289
|
+
};
|
|
290
|
+
//# sourceMappingURL=index.mjs.map
|