Documentation Index Fetch the complete documentation index at: https://mintlify.com/near/docs/llms.txt
Use this file to discover all available pages before exploring further.
Chain Signatures enable NEAR accounts and smart contracts to sign transactions for other blockchains, including Bitcoin, Ethereum, Solana, and more. This tutorial shows you how to control a NEAR account from another chain.
Overview
With Chain Signatures, you can:
Sign Bitcoin transactions from a NEAR account
Control Ethereum addresses from NEAR contracts
Create multi-chain applications with unified account management
Build cross-chain DeFi products
GitHub Repository View the complete Chain Signatures example
How it works
Derive chain-specific addresses
NEAR accounts can derive addresses for other chains using a path-based system: import { setupAdapter } from "@near-relay/client" ;
// Setup
const account = await setupAdapter ({
accountId: "your-account.testnet" ,
privateKey: "ed25519:..." ,
network: "testnet"
});
// Derive Ethereum address
const ethAddress = await account . deriveAddress ( "ethereum" , "your-path" );
console . log ( `Your Ethereum address: ${ ethAddress } ` );
// Derive Bitcoin address
const btcAddress = await account . deriveAddress ( "bitcoin" , "your-path" );
console . log ( `Your Bitcoin address: ${ btcAddress } ` );
The derivation path ensures deterministic address generation. The same path always produces the same address.
Create transaction for target chain
Build a transaction for the target blockchain: import { ethers } from "ethers" ;
// Create Ethereum transaction
const tx = {
to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" ,
value: ethers . parseEther ( "0.01" ),
gasLimit: 21000 ,
gasPrice: await provider . getGasPrice (),
nonce: await provider . getTransactionCount ( ethAddress ),
chainId: 1 , // Ethereum mainnet
};
// Serialize transaction
const serializedTx = ethers . Transaction . from ( tx ). unsignedSerialized ;
import * as bitcoin from "bitcoinjs-lib" ;
// Create Bitcoin transaction
const psbt = new bitcoin . Psbt ({ network: bitcoin . networks . bitcoin });
// Add inputs (UTXOs)
psbt . addInput ({
hash: utxo . txid ,
index: utxo . vout ,
witnessUtxo: {
script: Buffer . from ( utxo . scriptPubKey , "hex" ),
value: utxo . value ,
},
});
// Add output
psbt . addOutput ({
address: "bc1q..." ,
value: 100000 , // satoshis
});
// Get transaction hash to sign
const txHash = psbt . data . inputs [ 0 ]. witnessUtxo . script ;
Request signature from NEAR
Use the NEAR account to sign the transaction: // Request signature through Chain Signatures MPC
const signature = await account . signTransaction ({
transaction: serializedTx ,
path: "your-path" ,
chain: "ethereum"
});
console . log ( `Signature: ${ signature } ` );
Broadcast to target chain
Send the signed transaction to the target blockchain: // Attach signature to transaction
const signedTx = ethers . Transaction . from ({
... tx ,
signature: signature
}). serialized ;
// Broadcast
const txHash = await provider . broadcastTransaction ( signedTx );
console . log ( `Transaction: ${ txHash } ` );
// Add signature to PSBT
psbt . updateInput ( 0 , {
finalScriptWitness: signature
});
// Finalize and extract
psbt . finalizeAllInputs ();
const txHex = psbt . extractTransaction (). toHex ();
// Broadcast
const txid = await bitcoinRpc . sendRawTransaction ( txHex );
console . log ( `Transaction: ${ txid } ` );
Supported chains
Ethereum Full support for EVM chains including Ethereum, Polygon, Arbitrum, Optimism
Bitcoin Native Bitcoin support for BTC transactions
Solana Solana transaction signing support
Cosmos Support for Cosmos SDK chains
Dogecoin DOGE transaction signing
Example: Send ETH from NEAR
Complete example of sending ETH using a NEAR account:
import { setupAdapter } from "@near-relay/client" ;
import { ethers } from "ethers" ;
async function sendEth () {
// Initialize NEAR adapter
const account = await setupAdapter ({
accountId: "your-account.testnet" ,
privateKey: process . env . NEAR_PRIVATE_KEY ,
network: "testnet"
});
// Derive Ethereum address
const ethAddress = await account . deriveAddress ( "ethereum" , "my-eth-account" );
console . log ( `Sending from: ${ ethAddress } ` );
// Setup Ethereum provider
const provider = new ethers . JsonRpcProvider ( "https://eth.llamarpc.com" );
// Create transaction
const tx = {
to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" ,
value: ethers . parseEther ( "0.01" ),
gasLimit: 21000 ,
gasPrice: await provider . getGasPrice (),
nonce: await provider . getTransactionCount ( ethAddress ),
chainId: 1 ,
};
// Sign with NEAR
const serializedTx = ethers . Transaction . from ( tx ). unsignedSerialized ;
const signature = await account . signTransaction ({
transaction: serializedTx ,
path: "my-eth-account" ,
chain: "ethereum"
});
// Broadcast
const signedTx = ethers . Transaction . from ({
... tx ,
signature
}). serialized ;
const txHash = await provider . broadcastTransaction ( signedTx );
console . log ( `Success! Transaction: ${ txHash } ` );
}
sendEth (). catch ( console . error );
Using in smart contracts
Smart contracts can also request signatures:
use near_sdk :: {near, Promise , ext_contract};
#[ext_contract(ext_mpc)]
trait MpcContract {
fn sign ( & self , payload : Vec < u8 >, path : String , key_version : u32 ) -> Promise ;
}
#[near]
impl Contract {
pub fn sign_eth_transaction (
& self ,
transaction : Vec < u8 >,
path : String ,
) -> Promise {
ext_mpc :: ext ( "v1.signer-prod.testnet" . parse () . unwrap ())
. with_static_gas ( Gas :: from_tgas ( 250 ))
. sign ( transaction , path , 0 )
}
}
Security considerations
Use unique paths for different use cases
Never share paths publicly if they control valuable assets
Consider using account-specific path prefixes
Document your path structure
NEAR private keys control all derived addresses
Use hardware wallets for mainnet accounts
Implement access controls for contract-based signing
Audit signature request flows
Always verify transaction details before signing
Check recipient addresses carefully
Validate amounts and gas prices
Test with small amounts first
Next steps
Multi-chain DAO Build a DAO that governs multiple chains
Chain Signatures docs Learn more about Chain Signatures
NEAR Intents Use intents for cross-chain actions
Omnibridge Bridge assets across chains