Signers
A Signer in hethers is an abstraction of a Hedera Account, which can be used to sign messages and transactions and send signed transactions to the Hedera Network to execute state-changing operations.
The available operations depend largely on the sub-class used.
The Signer class is abstract and cannot be directly instantiated. Instead, use the Wallet.
Sub-classes must implement this. Returns a new instance of the Signer, connected to the provider.
const connectedSigner = signer.connect(provider);
Returns a Promise that resolves to the account address.
This is a Promise so that a Signer can be designed around an asynchronous source, such as hardware wallets.
Sub-classes must implement this.
await connectedSigner.getAddress();
// '0x0000000000000000000000000000000001C31552'
hethers.Signer.isSigner(connectedSigner)
// true
Returns the balance of this wallet.
await connectedSigner.getBalance();
// BigNumber { _hex: '0x01968b2cb94c', _isBigNumber: true }
Returns the chain ID this wallet is connected to.
await connectedSigner.getChainId();
// 291
Returns the result of calling using the transactionRequest, with this account address being used as the
from
field. Contrary to other EVM networks, static calls in Hedera are paid, thus executing a call
method is performed through the Signer
. The provider interface executes a ContractLocalCall
query under the hood. This is useful for calling getters on Contracts.await wallet.call({
to: "0x0000000000000000000000000000000001c42505",
gasLimit: 50000,
data: "0x3b3b57debf074faa138b72c65adbdcfb329847e4f2c04bde7f7dd7fcad5a52d2f395a558"
});
// '0x0000000000000000000000005555763613a12d8f3e73be831dff8598089d3dca'
Note:
to
can be either an address or an alias. This returns a Promise which resolves to the Raw Signature of message.
Sub-classes must implement this, however they may throw if signing a message is not supported
await connectedSigner.signMessage('message');
// 0xb462249048c96518da287131d64330f9530125c8d98e2f90f05f0108c6b74604397a268b3386e6c877d496daba65588e9700af66966762802d0139a7dfae537d1c
Returns a Promise which resolves to the signed transaction of the transactionRequest. This method does not populate any missing fields.
Sub-classes must implement this, however they may throw if signing a transaction is not supported, which is common for security reasons in many clients.
await connectedSigner.signTransaction(tx);
// 0x0ac1012abe010a530a1a0a0b0888a9fd900610d0b2b11412090800100018d2aa8c0e180012060800100018031880c2d72f22020878320072220a200a0e0a090800100018d2aa8c0e10c7010a0e0a090800100018d2aa8c0e10c80112670a650a210238b02dc2bf190448fd92eccaf6cc1129debc16f0c1b1b83a0a70cb206e1ec7793240ddad8b932de26c7de1eb6b983d6b214281f5523f50a84bf78b93bc52efc3eda68d76a969001322da336ca186857d27a27dec3b0a1647a42d53761702a5a5dadc
This method populates the transactionRequest with missing fields, using populateTransaction and returns a Promise which resolves to the transaction.
Sub-classes must implement this, however they may throw if sending a transaction is not supported or if the Wallet is offline and not connected to a Provider.
Signs the transaction with the key given upon creation. Transaction can be:
FileCreateTransaction
- when there is onlyfileChunk
field in thetransaction.customData
objectFileAppendTransaction
- when there is bothfileChunk
and afileId
fieldsContractCreateTransaction
- when there is abytecodeFileId
fieldContractExecuteTransaction
- when there is ato
field present. Ignores the other fieldsTransferTransaction
- when there is bothto
and avalue
fieldsAccountCreateTransaction
- when there is apublicKey
field in thetransaction.customData
object, alsoinitialBalance
can be provided as optional field incustomData
await connectedSigner.sendTransaction(tx);
// {
// transactionId: '0.0.29562194-1646220675-432278669',
// hash: '0xbc677be599074d716fcbc3422faef26d5318bfd00666ce95cd114ca82bdd64a65c71a7641f3a7b35283380fe94d6c12c',
// from: '0x0000000000000000000000000000000001c31552',
// chainId: 0,
// r: '',
// s: '',
// v: 0,
// customData: {},
// wait: [Function (anonymous)]
// }
It is very important that all important properties of a Signer are immutable. Since Hedera Hashgraph is very asynchronous and deals with critical data, keeping properties such as the provider and address static throughout the life-cycle of the Signer helps prevent serious issues and many other classes and libraries make this assumption.
A sub-class must extend Signer and must call
super()
. This is generally not required to be overridden, but may be needed to provide custom behaviour in sub-classes.
This should return a copy of the transactionRequest, with any properties needed by
call
and populateTransaction
(which is used by sendTransaction). It should also throw an error if any unknown key is specified. The default implementation checks only if valid TransactionRequest properties exist and adds
from
to the transaction if it does not exist. If there is a
from
field it must be verified to be equal to the Signer's address.await connectedSigner.checkTransaction(tx);
// {
// to: '0.0.29631750',
// value: 100,
// gasLimit: 50000,
// nodeId: '0.0.7',
// from: Promise { '0x0000000000000000000000000000000001C31552' }
// }
This is generally not required to be overridden, but may be needed to provide custom behaviour in sub-classes.
This should return a copy of transactionRequest, follow the same procedure as
checkTransaction
and fill in any properties required for sending a transaction. The result should have all promises resolved; if needed the resolveProperties utility function can be used for this. The default implementation calls
checkTransaction
and resolves to
, adds customData
based on the related operations on Signer.await connectedSigner.populateTransaction(tx);
// {
// to: '0x0000000000000000000000000000000001C42506',
// value: 100,
// nodeId: '0.0.6',
// from: '0x0000000000000000000000000000000001C31552',
// gasLimit: undefined,
// customData: { isCryptoTransfer: true }
// }
Create a new Wallet instance for privateKey and optionally connected to the provider.
Note: Using only a private Key for wallet initialization is not enough for further transaction execution in Hedera Network. Connecting to an account is mandatory for a fully operational wallet.
const privateKey = '0x3b6cd41ded6486add931390d4d3efa0bb2b311a8415cfe61716cac0234de035d';
const wallet = new hethers.Wallet(privateKey, provider);
Note: ECDSA privateKeys which do not start with
0x
are also accepted.const privateKey = '3b6cd41ded6486add931390d4d3efa0bb2b311a8415cfe61716cac0234de035d';
const wallet = new hethers.Wallet(privateKey, provider);
Create a new Wallet instance for ExternallyOwnedAccount and optionally connected to the provider.
Note: That wallet is fully operational, and can sign or send transactions, if accountId or address and privateKey are set up in the
ExternallyOwnedAccount
object.// Initialize wallet using address and private key
const eoaAddress = {
address: "0x0000000000000000000000000000000000000001",
privateKey: "0x074cc0bd188d1bc91f668c59b46a1e74fd13215661e5a7bd42ad0d324476295d"
};
const walletEoaAddress = new hethers.Wallet(eoaAddress, provider);
// Initialize wallet using hedera's account id and private key
const eoaAccount = {
account: "0.0.2",
privateKey: "0x074cc0bd148d1bc91f668c59b46a1e74fd13215661e5a7bd42ad0d324476295d"
};
const walletEoaAccount = new hethers.Wallet(eoaAccount, provider);
// Initialize wallet using alias and private key
const eoaAlias = {
alias: "0.0.BMAiA3xjpm4sULCFp5YuREmQDwJ7bbjrvFhi/ZnWaFNrRFGTh330h4aPqg8zZkJh7qzVjaNOWy1qpdt8bRbDFlc=",
privateKey: "0xc59f86eef4511f27450d3baf2139ae535061c4743a7f02a6e89fed014d551b4a"
}
const walletEoaAlias = new hethers.Wallet(eoaAlias, provider);
Returns a new Wallet with a random private key, generated from cryptographically secure entropy sources. If the current environment does not have a secure entropy source, an error is thrown. The library supports HIP-32, thus the created wallet will have an alias populated. In order for the wallet to be fully functional (be able to send transactions), it must be created by sending hbars to the alias for example.
const randomWallet = hethers.Wallet.createRandom();
randomWallet.privateKey
// '0x0bcdfa8acd4947d957a4b4ef4916a22bd8b34a82a3e238b554eb9c079dda1678'
Create an instance by decrypting an encrypted JSON wallet.
If progress is provided it will be called during decryption with a value between 0 and 1 indicating the progress towards completion.
const encryptedJson = await wallet.encrypt("secret");
const decryptedWallet = await hethers.Wallet.fromEncryptedJson(encryptedJson, "secret");
Create an instance from an encrypted JSON wallet.
This operation will operate synchronously which will lock up the user interface, possibly for a non-trivial duration. Most applications should use the asynchronous
fromEncryptedJson
instead.const encryptedJson = await wallet.encrypt("secret");
const decryptedWallet = hethers.Wallet.fromEncryptedJsonSync(encryptedJson, "secret");
Create an instance from a mnemonic phrase.
const mnemonic = "bullet network horse dash ahead kick donkey require blame ability punch surprise";
const mnemonicWallet = hethers.Wallet.fromMnemonic(mnemonic);
The address for the account this Wallet represents.
walletPkey.address;
// '0x0000000000000000000000000000000001c42505'
A Wallet instance is immutable, so if you wish to change the Provider, you may use the
connect
method to create a new instance connected to the desired provider. The uncompressed public key for this Wallet represents.
walletPkey.publicKey;
// '0x0438b02dc2bf190448fd92eccaf6cc1129debc16f0c1b1b83a0a70cb206e1ec7796ff1da61d00e30f43b461b880ced6f177a8b802f401a5e3b972bb48f25adf0b8'
Return a new instance of a fully operational wallet, that can be used for transaction signing and sending.
// Initialize the wallet
const privateKey = '0xc59f86eef3511f27450d3baf2139ae535061c4743a7f02a6e89fed014d551b4a';
const wallet = new hethers.Wallet(privateKey, provider);
// Connect to an account via hedera's account id
const connectedViaAccountId = wallet.connectAccount('0.0.1');
// Connect to an account via address
const connectedViaAddress = wallet.connectAccount('0x0000000000000000000000000000000000000001');
// Connect to an account via Account Type
const connectedViaAccount = wallet.connectAccount({
shard: BigInt(0),
realm: BigInt(0),
num: BigInt(1)
});
Return a new instance, connected to the provider.
const connectedWallet = wallet.connect(provider);
The transaction receipt containts the ID of the newly created account in the
TransactionReceipt.accountAddress
field. Note: There are two ways you can create an account either by using an existing account or by using an alias. If you have an existing account, you can use that account to create a new account and to pay for the associated transaction fees in hbar. If you do not have access to an existing account, you can create a testnet account via the Hedera Developer Portal or a mainnet account through one of the options listed here.
// create an account
const pubKey = randomAccount._signingKey().compressedPublicKey;
const txResponse = await wallet.createAccount(pubKey, BigInt(1));
const result = await txResponse.wait();
// once the account is created, it needs to be connected to provider
newAccount = new hethers.Wallet(result.accountAddress, provider);
await newAccount.getAddress()
The address for the account this Wallet represents.
await wallet.getAddress();
// '0x0000000000000000000000000000000001c42505'
Encrypt the wallet using password returning a Promise which resolves to a JSON wallet.
If progress is provided it will be called during decryption with a value between 0 and 1 indicating the progress towards completion.
const encryptedJson = await wallet.encrypt("secret");
await wallet.signMessage('message');
// '0xe1c58c8ea54a270eb99c14e1e6f7bbb14f2a16225556e5e7cc27e77d0f57cad4611fd46c747430e6b9df9cd51fa8430c993f664789034525629742f3ebb0be6d1c'
await wallet.signTransaction({
to: '0x0000000000000000000000000000000001c42506',
value: 1
});
// '0x0ac0012abd010a520a1b0a0c0898f1bd900610fe9ea5ad021209080010001885ca900e180012060800100018071880c2d72f22020878320072200a1e0a0d0a09080010001885ca900e10010a0d0a09080010001885ca900e100212670a650a21031477154d6d1be6a6d899f295c049a94f227f97299ac7853e4dbc41a1763fdada3240a16cce5413d6d3394680f7715eace55f5b19938e7fbaff0646456a614c6d5639262ac5a43bce51c062150e6c940aa299027903130de38810bcff39a5cdaba147'
await wallet.sendTransaction({
to: '0x0000000000000000000000000000000001c42506',
value: 1
});
// {
// transactionId: '0.0.29631749-1645182496-340392577',
// hash: '0x163e2457656ed52b79d0320c9852615b7f5d4032187cb6ba38244000d7634ccf171340ea53c1719e89de40f8d6eff76b',
// from: '0x0000000000000000000000000000000001c42505',
// chainId: 0,
// r: '',
// s: '',
// v: 0,
// customData: {},
// wait: [Function (anonymous)]
// }
This is an interface that contains a minimal set of properties required for Externally Owned Accounts(EOA) which can have certain operations performed, such as encoding as a JSON wallet.
The privateKey of this EOA.
The account Id of the EOA.
Last modified 1yr ago