interchainjs
Version:
InterchainJS is a JavaScript library for interacting with Cosmos SDK based blockchains.
184 lines (183 loc) • 6.97 kB
JavaScript
import { AminoSigner, DirectSigner, createCosmosSignerConfig } from '@interchainjs/cosmos';
import { LegacyEthereumSigner, EIP1559EthereumSigner, createEthereumSignerConfig } from '@interchainjs/ethereum';
import { SolanaSigner } from '@interchainjs/solana';
// Exported signer type constants
export const COSMOS_AMINO = 'cosmos_amino';
export const COSMOS_DIRECT = 'cosmos_direct';
export const ETHEREUM_LEGACY = 'ethereum_legacy';
export const ETHEREUM_EIP1559 = 'ethereum_eip1559';
export const SOLANA_STD = 'solana_std';
const SUPPORTED_SIGN_TYPES = [
COSMOS_AMINO,
COSMOS_DIRECT,
ETHEREUM_LEGACY,
ETHEREUM_EIP1559,
SOLANA_STD
];
/**
* Signer factory function that returns the appropriate signer instance
* based on the preferred sign type and configuration options.
*
* @template T - The specific signer type that extends IUniSigner
* @param walletOrSigner - Wallet instance or OfflineSigner for signing (Solana Keypair implements IWallet)
* @param options - Configuration options including preferredSignType and signer-specific settings
* @returns Configured signer instance of type T
* @throws Error if the sign type is unsupported or required dependencies are missing
*
* @example
* ```typescript
* import {
* getSigner,
* COSMOS_DIRECT,
* COSMOS_AMINO,
* ETHEREUM_LEGACY,
* ETHEREUM_EIP1559,
* SOLANA_STD
* } from '@interchainjs/interchain/core';
*
* // Create a Cosmos direct signer with specific type using IWallet
* const directSigner = getSigner<DirectSigner>(myWallet, {
* preferredSignType: COSMOS_DIRECT,
* signerOptions: {
* queryClient: cosmosQueryClient,
* chainId: 'cosmoshub-4',
* addressPrefix: 'cosmos'
* }
* });
*
* // Create an Amino signer with specific type using OfflineAminoSigner
* const aminoOfflineSigner = await wallet.toOfflineAminoSigner();
* const aminoSigner = getSigner<AminoSigner>(aminoOfflineSigner, {
* preferredSignType: COSMOS_AMINO,
* signerOptions: {
* queryClient: cosmosQueryClient,
* chainId: 'osmosis-1',
* addressPrefix: 'osmo'
* }
* });
*
* // Create an Ethereum legacy signer with specific type
* const legacySigner = getSigner<LegacyEthereumSigner>(myWallet, {
* preferredSignType: ETHEREUM_LEGACY,
* signerOptions: {
* queryClient: ethereumQueryClient,
* gasMultiplier: 1.2
* }
* });
*
* // Create a Solana signer using any IWallet (Solana Keypair implements IWallet)
* const solanaSigner = getSigner<SolanaSigner>(myKeypair, {
* preferredSignType: SOLANA_STD,
* signerOptions: {
* queryClient: solanaQueryClient,
* commitment: 'confirmed'
* }
* });
* ```
*/
export function getSigner(walletOrSigner, options) {
// Validate required parameters
if (!walletOrSigner) {
throw new Error('walletOrSigner is required');
}
if (!options) {
throw new Error('options are required');
}
if (!options.signerOptions) {
throw new Error('signerOptions are required');
}
switch (options.preferredSignType) {
case COSMOS_AMINO:
return createAminoSigner(walletOrSigner, options.signerOptions);
case COSMOS_DIRECT:
return createDirectSigner(walletOrSigner, options.signerOptions);
case SOLANA_STD:
return createSolanaSigner(walletOrSigner, options.signerOptions);
case ETHEREUM_LEGACY:
return createLegacyEthereumSigner(walletOrSigner, options.signerOptions);
case ETHEREUM_EIP1559:
return createEIP1559EthereumSigner(walletOrSigner, options.signerOptions);
default:
throw new Error(`Unsupported sign type: ${options.preferredSignType}. Supported types: ${SUPPORTED_SIGN_TYPES.join(', ')}`);
}
}
/**
* Creates a Cosmos Amino signer instance
*/
function createAminoSigner(walletOrSigner, signerOptions) {
try {
// Build configuration object from signerOptions
const config = createCosmosSignerConfig(signerOptions);
return new AminoSigner(walletOrSigner, config);
}
catch (error) {
throw new Error(`Failed to create Amino signer: ${error instanceof Error ? error.message : 'Unknown error'}. Make sure @interchainjs/cosmos is installed.`);
}
}
/**
* Creates a Cosmos Direct signer instance
*/
function createDirectSigner(walletOrSigner, signerOptions) {
try {
// Build configuration object from signerOptions
const config = createCosmosSignerConfig(signerOptions);
return new DirectSigner(walletOrSigner, config);
}
catch (error) {
throw new Error(`Failed to create Direct signer: ${error instanceof Error ? error.message : 'Unknown error'}. Make sure @interchainjs/cosmos is installed.`);
}
}
/**
* Creates a Solana signer instance
*/
function createSolanaSigner(walletOrSigner, signerOptions) {
const config = signerOptions;
if (!config?.queryClient) {
throw new Error('Failed to create Solana signer: queryClient is required in signerOptions');
}
if (isWalletAuth(walletOrSigner)) {
return new SolanaSigner(walletOrSigner, config);
}
throw new Error('Failed to create Solana signer: walletOrSigner must implement IWallet');
}
/**
* Creates an Ethereum Legacy signer instance
*/
function createLegacyEthereumSigner(walletOrSigner, signerOptions) {
// Ethereum signers only work with IWallet, not OfflineSigner
if (!('privateKeys' in walletOrSigner)) {
throw new Error('Ethereum signers require IWallet, OfflineSigner is not supported');
}
try {
// Build configuration object from signerOptions
const config = createEthereumSignerConfig(signerOptions);
return new LegacyEthereumSigner(walletOrSigner, config);
}
catch (error) {
throw new Error(`Failed to create Legacy Ethereum signer: ${error instanceof Error ? error.message : 'Unknown error'}. Make sure @interchainjs/ethereum is installed.`);
}
}
/**
* Creates an Ethereum EIP-1559 signer instance
*/
function createEIP1559EthereumSigner(walletOrSigner, signerOptions) {
// Ethereum signers only work with IWallet, not OfflineSigner
if (!('privateKeys' in walletOrSigner)) {
throw new Error('Ethereum signers require IWallet, OfflineSigner is not supported');
}
try {
// Build configuration object from signerOptions
const config = createEthereumSignerConfig(signerOptions);
return new EIP1559EthereumSigner(walletOrSigner, config);
}
catch (error) {
throw new Error(`Failed to create EIP-1559 Ethereum signer: ${error instanceof Error ? error.message : 'Unknown error'}. Make sure @interchainjs/ethereum is installed.`);
}
}
function isWalletAuth(value) {
if (!value || typeof value !== 'object') {
return false;
}
const candidate = value;
return typeof candidate.getAccounts === 'function' && typeof candidate.signByIndex === 'function';
}