Signing Transactions
Last updated
Last updated
The useWallet
hook/composable/primitive provides two methods for signing Algorand transactions:
signTransactions
- For directly signing transactions
transactionSigner
- For use with transaction composers that accept an algosdk.TransactionSigner
The method accepts either:
An array of algosdk.Transaction
objects
An array of encoded transactions (Uint8Array
)
An array of arrays of either of the above (for transaction groups)
It returns an array of Uint8Array | null
, where null
indicates an unsigned transaction.
import { useWallet } from '@txnlab/use-wallet-react'
import algosdk from 'algosdk'
function SendTransaction() {
const {
activeAddress,
signTransactions,
algodClient
} = useWallet()
const handleSend = async () => {
if (!activeAddress) return
try {
// Create transaction
const suggestedParams = await algodClient.getTransactionParams().do()
const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
sender: activeAddress,
receiver: activeAddress,
amount: 0,
suggestedParams
})
// Sign transaction
const signedTxns = await signTransactions([transaction])
// Send transaction
const { txid } = await algodClient.sendRawTransaction(signedTxns).do()
// Wait for confirmation
const result = await algosdk.waitForConfirmation(algodClient, txid, 4)
console.log(`Transaction confirmed at round ${result['confirmed-round']}`)
} catch (error) {
console.error('Error:', error)
}
}
return (
<button onClick={handleSend}>Send Transaction</button>
)
}
<script setup lang="ts">
import { useWallet } from '@txnlab/use-wallet-vue'
import algosdk from 'algosdk'
const {
activeAddress,
signTransactions,
algodClient
} = useWallet()
const handleSend = async () => {
if (!activeAddress.value) return
try {
// Create transaction
const suggestedParams = await algodClient.value.getTransactionParams().do()
const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
sender: activeAddress.value,
receiver: activeAddress.value,
amount: 0,
suggestedParams
})
// Sign transaction
const signedTxns = await signTransactions([transaction])
// Send transaction
const { txid } = await algodClient.value.sendRawTransaction(signedTxns).do()
// Wait for confirmation
const result = await algosdk.waitForConfirmation(algodClient.value, txid, 4)
console.log(`Transaction confirmed at round ${result['confirmed-round']}`)
} catch (error) {
console.error('Error:', error)
}
}
</script>
<template>
<button @click="handleSend">Send Transaction</button>
</template>
import { useWallet } from '@txnlab/use-wallet-solid'
import algosdk from 'algosdk'
function SendTransaction() {
const {
activeAddress,
signTransactions,
algodClient
} = useWallet()
const handleSend = async () => {
if (!activeAddress()) return
try {
// Create transaction
const suggestedParams = await algodClient().getTransactionParams().do()
const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
sender: activeAddress(),
receiver: activeAddress(),
amount: 0,
suggestedParams
})
// Sign transaction
const signedTxns = await signTransactions([transaction])
// Send transaction
const { txid } = await algodClient().sendRawTransaction(signedTxns).do()
// Wait for confirmation
const result = await algosdk.waitForConfirmation(algodClient(), txid, 4)
console.log(`Transaction confirmed at round ${result['confirmed-round']}`)
} catch (error) {
console.error('Error:', error)
}
}
return (
<button onClick={handleSend}>Send Transaction</button>
)
}
The AtomicTransactionComposer
(ATC) is the recommended way to build and execute groups of transactions, especially when working with smart contracts.
Here's an example using ATC to combine an ABI method call with a payment transaction:
import { useWallet } from '@txnlab/use-wallet-react'
import algosdk from 'algosdk'
function CallContractAtc() {
const {
activeAddress,
transactionSigner,
algodClient
} = useWallet()
const handleCall = async () => {
if (!activeAddress) return
try {
// Create ATC instance
const atc = new algosdk.AtomicTransactionComposer()
// Get suggested params
const suggestedParams = await algodClient.getTransactionParams().do()
// Add ABI method call
const method = algosdk.ABIMethod.fromSignature('hello(string)string')
atc.addMethodCall({
sender: activeAddress,
signer: transactionSigner,
appID: 123,
method,
methodArgs: ['World'],
suggestedParams,
})
// Add payment transaction
const paymentTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
sender: activeAddress,
receiver: activeAddress,
amount: 1000,
suggestedParams,
})
atc.addTransaction({ txn: paymentTxn, signer: transactionSigner })
// Execute transaction group
const result = await atc.execute(algodClient, 4)
console.log('Transaction confirmed:', result.txIDs[0])
// Get return value from ABI method
const returnValue = result.methodResults[0].returnValue
console.log('Return value:', returnValue)
} catch (error) {
console.error('Error:', error)
}
}
return (
<button onClick={handleCall}>Call Contract</button>
)
}
<script setup lang="ts">
import { useWallet } from '@txnlab/use-wallet-vue'
import algosdk from 'algosdk'
const {
activeAddress,
transactionSigner,
algodClient
} = useWallet()
const handleCall = async () => {
if (!activeAddress.value) return
try {
// Create ATC instance
const atc = new algosdk.AtomicTransactionComposer()
// Get suggested params
const suggestedParams = await algodClient.value.getTransactionParams().do()
// Add ABI method call
const method = algosdk.ABIMethod.fromSignature('hello(string)string')
atc.addMethodCall({
sender: activeAddress.value,
signer: transactionSigner,
appID: 123,
method,
methodArgs: ['World'],
suggestedParams,
})
// Add payment transaction
const paymentTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
sender: activeAddress.value,
receiver: activeAddress.value,
amount: 1000,
suggestedParams,
})
atc.addTransaction({ txn: paymentTxn, signer: transactionSigner })
// Execute transaction group
const result = await atc.execute(algodClient.value, 4)
console.log('Transaction confirmed:', result.txIDs[0])
// Get return value from ABI method
const returnValue = result.methodResults[0].returnValue
console.log('Return value:', returnValue)
} catch (error) {
console.error('Error:', error)
}
}
</script>
<template>
<button @click="handleCall">Call Contract</button>
</template>
import { useWallet } from '@txnlab/use-wallet-solid'
import algosdk from 'algosdk'
function CallContractAtc() {
const {
activeAddress,
transactionSigner,
algodClient
} = useWallet()
const handleCall = async () => {
if (!activeAddress()) return
try {
// Create ATC instance
const atc = new algosdk.AtomicTransactionComposer()
// Get suggested params
const suggestedParams = await algodClient().getTransactionParams().do()
// Add ABI method call
const method = algosdk.ABIMethod.fromSignature('hello(string)string')
atc.addMethodCall({
sender: activeAddress(),
signer: transactionSigner,
appID: 123,
method,
methodArgs: ['World'],
suggestedParams,
})
// Add payment transaction
const paymentTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
sender: activeAddress(),
receiver: activeAddress(),
amount: 1000,
suggestedParams,
})
atc.addTransaction({ txn: paymentTxn, signer: transactionSigner })
// Execute transaction group
const result = await atc.execute(algodClient(), 4)
console.log('Transaction confirmed:', result.txIDs[0])
// Get return value from ABI method
const returnValue = result.methodResults[0].returnValue
console.log('Return value:', returnValue)
} catch (error) {
console.error('Error:', error)
}
}
return (
<button onClick={handleCall}>Call Contract</button>
)
}
Smart contract interactions via typed clients
Transaction creation and composition
Fee calculations and simulation
Here's the same transaction group (ABI method call + payment) composed using AlgoKit Utils:
import { useWallet } from '@txnlab/use-wallet-react'
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
import { HelloWorldClient } from './artifacts/HelloWorld/client'
function CallContractAlgoKit() {
const {
activeAddress,
transactionSigner,
algodClient
} = useWallet()
const handleCall = async () => {
if (!activeAddress) return
try {
// Initialize AlgorandClient with algodClient and signer from use-wallet
const algorand = AlgorandClient
.fromClients({ algod: algodClient })
.setSigner(activeAddress, transactionSigner)
// Get typed app client instance
const client = algorand.client.getTypedAppClientById(HelloWorldClient, {
appId: 123n,
})
// Compose and send transaction group
const result = await client
.newGroup()
// Add ABI method call (type-safe!)
.hello({ args: { name: 'World' } })
// Add payment transaction
.addTransaction(
algorand.createTransaction.payment({
sender: activeAddress(),
receiver: activeAddress(),
amount: (1000).microAlgo()
})
)
.execute()
console.log('Transaction confirmed:', result.transaction.txID())
console.log('Return value:', result.return)
} catch (error) {
console.error('Error:', error)
}
}
return (
<button onClick={handleCall}>Call Contract</button>
)
}
<script setup lang="ts">
import { useWallet } from '@txnlab/use-wallet-vue'
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
import { HelloWorldClient } from './artifacts/HelloWorld/client'
const {
activeAddress,
transactionSigner,
algodClient
} = useWallet()
const handleCall = async () => {
if (!activeAddress.value) return
try {
// Initialize AlgorandClient with algodClient and signer from use-wallet
const algorand = AlgorandClient
.fromClients({ algod: algodClient.value })
.setSigner(activeAddress.value, transactionSigner)
// Get typed app client instance
const client = algorand.client.getTypedAppClientById(HelloWorldClient, {
appId: 123n,
})
// Compose and send transaction group
const result = await client
.newGroup()
// Add ABI method call (type-safe!)
.hello({ args: { name: 'World' } })
// Add payment transaction
.addTransaction(
algorand.createTransaction.payment({
sender: activeAddress(),
receiver: activeAddress(),
amount: (1000).microAlgo()
})
)
.execute()
console.log('Transaction confirmed:', result.transaction.txID())
console.log('Return value:', result.return)
} catch (error) {
console.error('Error:', error)
}
}
</script>
<template>
<button @click="handleCall">Call Contract</button>
</template>
import { useWallet } from '@txnlab/use-wallet-solid'
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
import { HelloWorldClient } from './artifacts/HelloWorld/client'
function CallContractAlgoKit() {
const {
activeAddress,
transactionSigner,
algodClient
} = useWallet()
const handleCall = async () => {
if (!activeAddress()) return
try {
// Initialize AlgorandClient with algodClient and signer from use-wallet
const algorand = AlgorandClient
.fromClients({ algod: algodClient() })
.setSigner(activeAddress(), transactionSigner)
// Get typed app client instance
const client = algorand.client.getTypedAppClientById(HelloWorldClient, {
appId: 123n,
})
// Compose and send transaction group
const result = await client
.newGroup()
// Add ABI method call (type-safe!)
.hello({ args: { name: 'World' } })
// Add payment transaction
.addTransaction(
algorand.createTransaction.payment({
sender: activeAddress(),
receiver: activeAddress(),
amount: (1000).microAlgo()
})
)
.execute()
console.log('Transaction confirmed:', result.transaction.txID())
console.log('Return value:', result.return)
} catch (error) {
console.error('Error:', error)
}
}
return (
<button onClick={handleCall}>Call Contract</button>
)
}
For more information, see:
For more information about constructing and sending transactions with the Algorand JavaScript SDK, see the guide in the Algorand Developer Portal.
The provides a typed algosdk.TransactionSigner
that can be used with transaction composers. This is particularly useful when working with ABI method calls or when you need to compose multiple transactions.
For more information, see the in the Algorand Developer Portal.
The most powerful way to interact with Algorand is using ' AlgorandClient
. This class provides a unified interface for all Algorand functionality, including: