Hedera
  • Welcome to Hedera — let’s build the future
  • Getting Started
    • Environment Setup
    • Web2 Developers
      • Transfer HBAR
      • Create a Token
      • Create a Topic
    • EVM Developers
      • Deploy a Contract
  • Tutorials
    • Smart Contracts
      • How to Mint & Burn an ERC-721 Token Using Hardhat and Ethers (Part 1)
      • How to Set Access Control, a Token URI, Pause, and Transfer an ERC-721 Token Using Hardhat (Part 2)
      • How to Verify a Smart Contract on HashScan
      • Deploy a Smart Contract Using Remix
      • Deploy a Smart Contract Using Hardhat and Hiero JSON-RPC Relay
      • Deploy Your First Smart Contract
      • Deploy a Contract Using the Hedera Token Service
      • Send and Receive HBAR Using Solidity Smart Contracts
      • Deploy By Leveraging Ethereum Developer Tools On Hedera
      • Deploy a Subgraph Using The Graph and Hedera JSON-RPC Relay
      • Deploy Smart Contracts on Hedera Using Truffle
      • The Power of Native Hedera Tokens as ERC-20 Tokens: A step-by-step guide
      • HTS x EVM - Part 1: How to Mint NFTs
      • HTS x EVM - Part 2: KYC & Update
      • HTS x EVM - Part 3: How to Pause, Freeze, Wipe, and Delete NFTs
      • Hedera Smart Contracts Workshop
        • Setup
        • Solidity
        • Hedera SDK JS
        • Hardhat and EthersJs
        • Outro
      • Foundry
        • How to Setup Foundry and Write a Basic Unit Test
        • How to Deploy and Verify a Hedera Smart Contract with Foundry
        • How to Test A Solidity Event
        • How to Fork Testnet on Latest Block
    • Consensus
      • Submit Your First Message
      • Submit Message to Private Topic
      • Query Messages with Mirror Node
    • Tokens
      • Create and Transfer Your First NFT
      • Create and Transfer Your First Fungible Token
      • Create and Transfer an NFT using a Solidity Contract
      • Structure Your Token Metadata Using JSON Schema V2
      • Hedera Token Service - Part 1: How to Mint NFTs
      • Hedera Token Service - Part 2: KYC, Update, and Scheduled Transactions
      • Hedera Token Service - Part 3: How to Pause, Freeze, Wipe, and Delete NFTs
      • Create Your First Frictionless Airdrop Campaign
    • Local Node
      • How to Run Hedera Local Node in a Cloud Development Environment (CDE)
        • Run a Local Node in Gitpod
        • Run a Local Node in Codespaces
      • How to Set Up a Hedera Local Node
      • Set Up a Hedera Local Node using the NPM CLI
    • More Tutorials
      • Create and Fund Your Hedera Testnet Account
      • How to Create a Personal Access Token (API Key) on the Hedera Portal
      • How to Auto-Create Hedera Accounts with HBAR and Token Transfers
      • How to Configure a Mirror Node and Query Data
      • How to Generate a Random Number on Hedera
      • Get Started with the Hedera Consensus Service Fabric Plugin
        • Virtual Environment Setup
      • Schedule Your First Transaction
      • How to Connect to Hedera Networks Over RPC
        • Configuring Hashio RPC endpoints
        • Configuring Hiero JSON-RPC Relay endpoints
        • Configuring Validation Cloud RPC endpoints
      • JavaScript Testing
      • Create a Hedera DApp Integrated with WalletConnect
      • How to Connect MetaMask to Hedera
    • Demo Applications
    • Starter Projects
    • Building on Hedera (course)
  • Networks
    • Mainnet
      • Mainnet Accounts
      • Mainnet Consensus Nodes
        • Node Requirements
          • FAQ
      • Fees
        • Transaction Records
    • Testnets
      • Testnet Accounts
      • Testnet Consensus Nodes
    • Localnet
      • Single Node Configuration
      • Multinode Configuration
    • Network Explorers and Tools
    • Release Notes
      • Consensus Node
      • Hedera Mirror Node
  • Core Concepts
    • Accounts
      • Account Creation
      • Auto Account Creation
      • Account Properties
    • Keys and Signatures
    • Schedule Transaction
    • Smart Contracts
      • Understanding Hedera's EVM Differences and Compatibility
        • For EVM Developers Migrating to Hedera
          • Accounts, Signature Verification & Keys (ECDSA vs. ED25519)
          • JSON-RPC Relay and EVM Tooling
          • Token Management with Hedera Token Service
          • Decimal Handling (8 vs. 18 Decimals)
          • Handling HBAR Transfers in Contracts
        • For Hedera-Native Developers Adding Smart Contract Functionality
          • Integrating ED25519 Accounts and Advanced Features Into Smart Contracts
          • JSON-RPC Relay and State Queries
          • Extending Token Management with Smart Contracts
      • Creating Smart Contracts
      • Compiling Smart Contracts
      • System Smart Contracts
        • Hedera Account Service
        • Hedera Schedule Service
      • Gas and Fees
      • JSON-RPC Relay
      • Deploying Smart Contracts
      • Smart Contract Addresses
      • Verifying Smart Contracts
      • Smart Contract Traceability
      • Tokens Managed by Smart Contracts
        • ERC-20 (Fungible Tokens)
        • ERC-721 (Non-Fungible Token)
        • ERC-3643 Real World Assets (RWA)
        • ERC-1363 (Payable Tokens)
        • Hedera Token Service System Contract
      • Wrapped HBAR (WHBAR)
      • Smart Contract Rent
      • Smart Contract Security
      • EVM Archive Node Queries
    • Tokens
      • Tokenization on Hedera
      • Hedera Token Service (HTS) Native Tokenization
        • Token Types and ID Formats
        • Token Properties
        • Token Creation
        • Custom Fee Schedule
        • Token Airdrops
      • ERC/EVM-Compatible Tokenization
      • Hybrid (HTS + EVM ) Tokenization
    • Staking
      • Staking Program
      • Stake HBAR
    • Hashgraph Consensus Algorithm
      • Gossip About Gossip
      • Virtual Voting
    • Transactions and Queries
      • Transaction Properties
    • State and History
    • Mirror Nodes
      • Hedera Mirror Node
      • One Click Mirror Node Deployment
      • Run Your Own Mirror Node
        • Run Your Own Mirror Node with Google Cloud Storage (GCS)
        • Run Your Mirror Node with Amazon Web Services S3 (AWS)
  • Open Source Solutions and Integrations
    • AI Tools for Developers
      • Hedera AI Agent Kit
      • ElizaOS Plugin for Hedera
      • Hedera Hivemind
      • Kapa AI
    • Asset Tokenization Studio (ATS)
      • Web User Interface (UI)
      • Frequently Asked Questions (FAQs)
    • HashioDAO
      • Governance Token DAO
      • NFT DAO
      • Multisig DAO
      • DAO Proposals
      • Local Environment Setup
    • Hedera CLI
    • Hedera Custodians Library
      • How to use it
    • Hedera Developer Playground
    • Hedera Wallet Snap By MetaMask
      • Hedera Wallet Snap Documentation
      • Tutorial: MetaMask Snaps – What Are They and How to Use Them
    • Interoperability and Bridging
      • LayerZero
    • NFT Studio
      • Airdrop List Verifier
      • Metadata Validator
      • NFT Rarity Inspector
      • NFT Token Holders List Builder
      • NFT Risk Calculator
      • Token Balance Snapshot
      • Hedera NFT SDK
    • Oracle Networks
      • Chainlink Oracles
      • Pyth Oracles
      • Supra Oracles
    • Stablecoin Studio
      • Core Concepts
      • Web UI Application
      • CLI Management
      • TypeScript SDK
    • Hedera Guardian
    • Hedera WalletConnect
  • SDKs & APIs
    • SDKs
      • Build Your Hedera Client
      • Set Up Your Local Network
      • Network Address Book
      • Keys
        • Generate a new key pair
        • Import an existing key
        • Create a key list
        • Create a threshold key
        • Generate a mnemonic phrase
        • Recover keys from a mnemonic phrase
      • HBAR
      • Specialized Types
      • Pseudorandom Number Generator
      • Transactions
        • Create a Batch Transaction
        • Transaction ID
        • Modify transaction fields
        • Create an unsigned transaction
        • Manually sign a transaction
        • Submit a transaction
        • Sign a multisignature transaction
        • Get a transaction receipt
        • Get a transaction record
      • Schedule Transaction
        • Schedule ID
        • Create a schedule transaction
        • Sign a scheduled transaction
        • Delete a schedule transaction
        • Get schedule info
        • Network Response Messages
      • Queries
      • General Network Response Messages
      • Accounts and HBAR
        • Create an account
        • Update an account
        • Transfer cryptocurrency
        • Approve an allowance
        • Delete an allowance
        • Delete an account
        • Get account balance
        • Get account info
        • Network Response Messages
      • Consensus Service
        • Create a topic
        • Update a topic
        • Submit a message
        • Delete a topic
        • Get topic messages
        • Get topic info
        • Network Response
      • Token Service
        • Token ID
        • NFT ID
        • Token types
        • Create a token
        • Custom token fees
        • Update a token
        • Update token custom fees
        • Update NFT metadata
        • Transfer tokens
        • Airdrop a token
        • Claim a token
        • Cancel a token
        • Reject a token
        • Delete a token
        • Mint a token
        • Burn a token
        • Freeze an account
        • Unfreeze an account
        • Enable KYC account flag
        • Disable KYC account flag
        • Associate tokens to an account
        • Dissociate tokens from an account
        • Pause a token
        • Unpause a token
        • Wipe a token
        • Atomic swaps
        • Get account token balance
        • Get token info
        • Get NFT info
        • Network Response Messages
      • File Service
        • Create a file
        • Append to a file
        • Update a file
        • Delete a file
        • Get file contents
        • Get file info
        • Network Response Messages
      • Smart Contract Service
        • Delegate Contract ID
        • Create a smart contract
        • Update a smart contract
        • Delete a smart contract
        • Call a smart contract function
        • Ethereum transaction
        • Get a smart contract function
        • Get smart contract bytecode
        • Get smart contract info
        • Hedera Service Solidity Libraries
        • Network Response Messages
      • Signature Provider
        • Provider
        • Signer
        • Wallet
        • Local Provider
    • Mirror Node REST API
      • Accounts
      • Balances
      • Blocks
      • Schedule Transactions
      • Smart Contracts
      • Tokens
      • Topics
      • Transactions
      • Network
    • Hedera Consensus Service gRPC API
    • Hedera APIs
      • Basic Types
        • AccountAmount
        • AccountID
        • ContractID
        • CryptoAllowance
        • CurrentAndNextFeeSchedule
        • FeeComponents
        • FeeData
        • FeeSchedule
        • FileID
        • Fraction
        • HederaFunctionality
        • Key
        • KeyList
        • NftAllowance
        • NftTransfer
        • NodeAddress
        • NodeAddressBook
        • RealmID
        • ScheduleID
        • SemanticVersion
        • ServicesConfigurationList
        • ServiceEndpoint
        • Setting
        • ShardID
        • Signature
        • SignatureList
        • SignatureMap
        • SignaturePair
        • SubType
        • TransferList
        • TransactionID
        • ThresholdKey
        • ThresholdSignature
        • TokenAllowance
        • TokenBalance
        • TokenBalances
        • TokenFreezeStatus
        • TokenPauseStatus
        • TokenID
        • TokenKycStatus
        • TokenRelationship
        • TokenTransferList
        • TokenType
        • TokenSupplyType
        • TopicID
        • TransactionFeeSchedule
      • Cryptocurrency Accounts
        • CryptoService
        • CryptApproveAllowance
        • CryptoDeleteAllowance
        • CryptoCreate
        • CryptoTransfer
        • CryptoUpdate
        • CryptoDelete
        • CryptoGetAccountBalance
        • CryptoGetAccountRecords
        • CryptoGetInfo
        • CryptoGetStakers
      • Consensus Service
        • Consensus Service
        • ConsensusCreateTopic
        • ConsensusUpdateTopic
        • ConsensusSubmitMessage
        • ConsensusDeleteTopic
        • ConsensusTopicInfo
        • ConsensusGetTopicInfo
      • Schedule Service
        • ScheduleService
        • SchedulableTransactionBody
        • ScheduleCreate
        • ScheduleDelete
        • ScheduleSign
        • ScheduleGetInfo
      • Token Service
        • TokenService
        • CustomFees
          • AssessedCustomFee
          • CustomFee
          • FractionalFee
          • FixedFee
          • RoyaltyFee
        • TokenCreate
        • TokenUpdate
        • TokenFeeScheduleUpdate
        • TokenDelete
        • TokenMint
        • TokenBurn
        • TokenFreezeAccount
        • TokenUnfreezeAccount
        • TokenGrantKyc
        • TokenRevokeKyc
        • TokenAssociate
        • TokenDissociate
        • TokenWipeAccount
        • TokenPause
        • TokenUnpause
        • TokenGetInfo
        • TokenGetNftInfo
        • TokenGetNftInfos
        • TokenGetAccountNftInfo
      • File Service
        • FileService
        • FileCreate
        • FileAppend
        • FileUpdate
        • FileDelete
        • FileGetContents
        • FileGetInfo
      • Smart Contracts
        • SmartContractService
        • ContractCall
        • ContractCallLocal
        • ContractCreate
        • ContractUpdate
        • ContractDelete
        • ContractGetByteCode
        • ContractGetInfo
        • ContractGetRecords
      • Miscellaneous
        • Duration
        • ExchangeRate
        • Freeze
        • FreezeType
        • GetByKey
        • GetBySolidityID
        • NetworkGetVersionInfo
        • NetworkService
        • Query
        • QueryHeader
        • Response
        • ResponseCode
        • ResponseHeader
        • SystemDelete
        • SystemUndelete
        • TimeStamp
        • Transaction
        • TransactionBody
        • TransactionContents
        • TransactionGetFastRecord
        • TransactionGetReceipt
        • TransactionGetRecord
        • TransactionReceipt
        • TransactionRecord
        • TransactionResponse
        • UncheckedSubmit
    • Hedera Status API
  • Support & Community
    • Glossary
    • Contributing to Hedera documentation
      • Contribution Guidelines
        • Creating Issues
        • Creating Pull Requests
        • Hedera Improvement Proposal (HIP)
        • Submit Demo Applications
      • Style Guide
        • Understanding different types of documentation
        • Use of HBAR and tinybars
        • Use of web2 and web3
        • Language and grammar
        • Formatting
        • Punctuation
        • GitBook Markdown Syntax
    • Discord
    • GitHub
    • Stack Overflow
    • Hedera Blog
    • Bug Bounty
    • Hedera Help
    • Documentation Survey
    • Meetups
    • Brand Guidelines
    • Status Page
Powered by GitBook
LogoLogo

INTRODUCTION

  • Fees
  • Core Concepts
  • Network Information

TOOLS

  • Bridge
  • Oracles
  • Explorers
  • Developer Portal & Faucet

RESOURCES

  • Status
  • Bug Bounty
  • Build on Hedera (course)
  • Documentation Survey
On this page
  • 1. Create the transaction
  • 2. Collect required signatures
  • 3. Create a single transaction with all three signatures
  • 4. Verify the required signers public keys
  • 5. Submit the transaction

Was this helpful?

Edit on GitHub
  1. SDKs & APIs
  2. SDKs
  3. Transactions

Sign a multisignature transaction

Hedera supports multisignature transactions. This means a Hedera transaction can require more than one key to sign a transaction in order for it to be processed on a Hedera network. These keys can be set up as a key list where all the keys in the specified list are required to sign the transaction or a threshold key where only a subset of the keys from a specified list are required to sign the transaction. The example below shows how you can use multiple keys to sign and submit a transaction.

Note: This example uses version 2.0 of the SDKs.

1. Create the transaction

In this example, we will use a transfer transaction that requires 3 keys to sign the transaction. If all 3 keys do not sign the transaction, the transaction will not execute and an "INVALID_SIGNATURE" response will be returned from the network. The senderAccountId is a Hedera account that was created with a key list of 3 keys. Since the sender account is required to sign in a transfer transaction, all three keys are required to sign to complete the transfer of hbars from the sender account to the recipient account. The recipient account is not required to sign the transaction.

After you create the transfer transaction, you will need to freeze (freezeWith(client)) the transaction from further modification so that transaction cannot be tampered with. This ensures each signer is signing the same exact transaction. The transaction is then shared with each of the three signers to sign with their private keys.

It is required to set the account ID of the node(s) the transaction will be submitted to when freezing a transaction for signatures. To set the node account ID(s) you apply the .setNodeAccountIds() method.

//The node account ID to submit the transaction to. You can add more than 1 node account ID to the list.
List<AccountId> nodeId = Collections.singletonList(new AccountId(3));

//Create the transfer transaction
TransferTransaction transferTransaction = new TransferTransaction()
        .addHbarTransfer(senderAccountId, new Hbar(1))
        .addHbarTransfer(receiverAccountId, new Hbar(-1)
        .setNodeAccountIds(nodeId);

//Freeze the transaction from any further modifications
TransferTransaction transaction = transferTransaction.freezeWith(client);
//The node account ID to submit the transaction to. You can add more than 1 node account ID to the list
const nodeId = [];
nodeId.push(new AccountId(3));

//Create the transfer transaction
const transferTransaction = new TransferTransaction()
    .addHbarTransfer(senderAccountId, new Hbar(1))
    .addHbarTransfer(receiverAccountId, new Hbar(-1))
    .setNodeAccountIds(nodeId);

//Freeze the transaction from further modifications
const transaction = await transferTransaction.freezeWith(client);
nodeAccountId, err := hedera.AccountIDFromString("0.0.3")
if err != nil {
}

nodeIdList := []hedera.AccountID{nodeAccountId}

//Create the transfer transaction
transferTransaction := hedera.NewTransferTransaction().
    AddHbarTransfer(senderAccountId, hedera.NewHbar(1)).
        AddHbarTransfer(receiverAccountId, hedera.NewHbar(-1)).
        SetNodeAccountIDs(nodeIdList)

//Freeze the transaction from any further modifications
transaction, err := transferTransaction.FreezeWith(client)

2. Collect required signatures

Each signer can sign the transactionwith their private key. The signed transactions are then returned to you from each of the 3 signers, resulting in 3 separate signature bytes. The sample code below is for illustrative purposes as you would not have the private keys to sign the transaction for each signer.

//Signer one signs the transaction with their private key
byte[] signature1 = privateKeySigner1.signTransaction(transaction);

//Signer two signs the transaction with their private key
byte[] signature2 = privateKeySigner2.signTransaction(transaction);

//Signer three signs the transaction with their private key
byte[] signature3 = privateKeySigner3.signTransaction(transaction);

//signature1, signature2, and signature3 are returned back to you
//Signer one signs the transaction with their private key
const signature1 = privateKeySigner1.signTransaction(transaction);

//Signer two signs the transaction with their private key
const signature2 = privateKeySigner2.signTransaction(transaction);

//Signer three signs the transaction with their private key
const signature3 = privateKeySigner3.signTransaction(transaction);

//signature1, signature2, and signature3 are returned back to you
//Signer one signs the transaction with their private key
signature1, err := privateKeySigner1.SignTransaction(transaction.Transaction)
if err != nil {
}

//Signer two signs the transaction with their private key
signature2, err := privateKeySigner2.SignTransaction(transaction.Transaction)
if err != nil {
}

//Signer three signs the transaction with their private key
signature3, err := privateKeySigner3.SignTransaction(transaction.Transaction)
if err != nil {
}

//signature1, signature2, and signature3 are returned back to you

3. Create a single transaction with all three signatures

Once you have collected all three signature bytes (signature1, signature2, signature 3), you will then apply them to the transaction (transaction) to create a single transaction with all three signatures to submit to the network. You will take the transaction that we started with and apply the signature bytes to the transaction using addSignature(). You will need the public keys of each of the signers to include in the method.

You can add as many signatures to a single transaction as long as the transaction size does not exceed 6,144 kb. Each additional signature applied to the transaction will increase the transaction fee from its base cost of $0.0001. If the transaction fee increases beyond the SDK's default max transaction fee of 1 hbar, you will need to update the max transaction fee value by calling the .setMaxTransactionFee() before submitting the transaction to the network.

//Collate all three signatures with the transaction
TransferTransaction signedTransaction = transaction.addSignature(publicKey1, signature1).addSignature(publicKey2, signature2).addSignature(publicKey3, signature3);
//Collate all three signatures with the transaction
const signedTransaction = transaction.addSignature(publicKey1, signature1).addSignature(publicKey2, signature2).addSignature(publicKey3, signature3);
//Collate all three signatures with the transaction
signedTransaction := transaction.AddSignature(publicKey1, signature1).AddSignature(publicKey2, signature2).AddSignature(publicKey3, signature3)

4. Verify the required signers public keys

Before you submit the transaction to a Hedera network, you may want to verify the keys that signed the transaction. You can view the public keys that signed the transaction by calling .getSignatures() to signedTransaction. You can then compare the public keys returned from the signedTransaction.getSignatures() to the public keys of each of the signers to verify the required keys have signed. Both the public key and public key bytes are returned.

//Print all public keys that signed the transaction
System.out.println("The public keys that signed the transaction " +signedTransaction.getSignatures());
//Print all public keys that signed the transaction
console.log("The public keys that signed the transaction  " +signedTransaction.getSignatures());
//Print all public keys that signed the transaction
signatures, err := signedTransaction.GetSignatures()
fmt.Println("The public keys that signed the transaction ", signatures)

5. Submit the transaction

//Submit the transaction to a Hedera network
TransactionResponse submitTx = signedTransaction.execute(client);

//Get the transaction ID
TransactionId txId = submitTx.transactionId;

//Print the transaction ID to the console
System.out.println("The transaction ID " +txId);
//Submit the transaction to a Hedera network
const submitTx = await signedTransaction.execute(client);

//Get the transaction ID
const txId = submitTx.transactionId.toString();

//Print the transaction ID to the console
console.log("The transaction ID " +txId);
//Submit the transaction to a Hedera network
submitTx, err := signedTransaction.Execute(client)

//Get the transaction ID
txId := submitTx.TransactionID

//Print the transaction ID to the console
fmt.Println("The transaction ID ", txId)
PreviousSubmit a transactionNextGet a transaction receipt

Last updated 2 months ago

Was this helpful?

We are now ready to submit the transfer transaction to a Hedera network. To submit the transaction, we will apply the .execute() method to signedTransaction. After the transaction is submitted, we will print the transaction ID to the console. You can use the transaction ID to search for transaction details in a mirror node explorer like or . Be sure to select the correct network when searching for the transaction in a mirror node explorer. You can also check the status of a transaction by requesting the of the transaction and obtaining the status.

DragonGlass
Hashscan
receipt