- About Keychain
- Usage
- Operations
- hive_keychain
- requestHandshake
- requestEncodeMessage
- requestEncodeWithKeys
- requestVerifyKey
- requestSignBuffer
- requestAddAccountAuthority
- requestRemoveAccountAuthority
- requestAddKeyAuthority
- requestRemoveKeyAuthority
- requestBroadcast
- requestSignTx
- requestSignedCall
- requestPost
- requestVote
- requestCustomJson
- requestTransfer
- requestSendToken
- requestDelegation
- requestWitnessVote
- requestProxy
- requestPowerUp
- requestPowerDown
- requestCreateClaimedAccount
- requestCreateProposal
- requestRemoveProposal
- requestUpdateProposalVote
- requestAddAccount
- requestConversion
- requestRecurrentTransfer
- requestSwap
- hive_keychain
- requestCallback
Putting private keys directly into websites is not safe or secure, even ones run by reputable community members. Yet this is currently how nearly every Hive-based site or service currently works. On top of that, most Hive users likely use their master password which is even worse.
The Vessel desktop wallet software is a secure alternative, but it is too difficult to use for the majority of Hive users and does not easily interact with websites - which is Hive's primary use case.
On Ethereum, you never have to enter your private key into a website to use a dApp. You can just use a browser extension like Metamask, which dApp websites can interface with to securely store your keys and broadcast transactions to the blockchain.
Hive Keychain aims to bring the security and ease-of-use of Metamask to the Hive blockchain platform.
You can download and install the latest published version of the extension for the following browsers:
- Google Chrome (or Opera/Brave): on Chrome Store
- Export your keys from Steem keychain (in settings)
- Download this repository as zip
- Unzip the downloaded folder
- Right click on any existing extension > Manage my extensions.
- Activate developer mode.
- Click "Load Unpacked" and select the unzipped folder.
- Import your keys (use the same master password)
- Firefox: on Firefox Addon Store
The Hive Keychain extension includes the following features:
- Store an unlimited number of Hive account keys, encrypted with AES
- View balances, transaction history, voting power, and resource credits
- Send HIVE and HBD transfers, manage witness votes, and update HP delegation right from the extension
- Manage your Hive Engine tokens
- Power up or down
- Securely interact with Hive-based websites that have integrated with Hive Keychain
- Manage transaction confirmation preferences by account and by website
- Locks automatically on browser shutdown or manually using the lock button
Websites can currently request the Hive Keychain extension to perform the following functions / broadcast operations:
- Send a handshake to make sure the extension is installed
- Decrypt a message encrypted by a Hive account private key (commonly used for "logging in")
- Post a comment (top level or reply)
- Broadcast a vote
- Broadcast a custom JSON operation
- Send a transfer
- Send Hive Engine tokens
- Send Delegations
- Power up/down
- Vote for witnesses
- Create/Remove/Vote for proposals
- Create claimed accounts
- Sign Tx
An example of a web page that interacts with the extension is included in the "example" folder in the repo. You can test it by running a local HTTP server and going to http://localhost:1337/main.html in your browser.
cd example
python -m http.server 1337 //or any other method to run a static server
NOTE: On localhost, it will run on port 1337.
To login, you can encode a message from your backend and verify that the user can decode it using the requestVerifyKey
method.
See an example in this project by @howo (@steempress witness):
Alternatively, you can use requestSignTx
and verify the signature on your backend.
This npm module makes it easy to add Keychain support within the browser. It also includes helpful functions to check whether Keychain was used before. It was developed by @therealwolf (witness).
The Hive Keychain extension will inject a "hive_keychain" JavaScript into all web pages opened in the browser while the extension is running. You can therefore check if the current user has the extension installed using the following code:
Use the hive_keychain
methods listed below to issue requests to the Hive blockchain.
This function is called to verify Keychain installation on a user's device
callback
function Confirms Keychain installation (has no parameters)
This function is called to verify that the user has a certain authority over an account, by requesting to decode a message
username
String Hive account to perform the requestreceiver
String Account that will decode the stringmessage
String Message to be encryptedkey
String Type of key. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the request
const keychain = window.hive_keychain;
const message = username + Date.now();
keychain.requestEncodeMessage(username, myUsername, message, 'Memo', (response) => {
if (response.success) {
const encodedMessage = response.result;
// Send message to a server where you can use your private key to decode it
}
});
This function is called to allow encoding a message with multiple receivers. This is used in the case of multisig
username
String Hive account to perform the requestpublicKeys
Array<String> Key that can decode the stringmessage
String Message to be encryptedkey
String Type of key. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the request
const keychain = window.hive_keychain;
const message = username + Date.now();
keychain.requestEncodeMessage(username, [pubKey1, pubKey2], message, 'Memo', (response) => {
if (response.success) {
const encodedMessages = response.result;
// Send message to a server where you can use your private key to decode it
}
});
This function is called to verify that the user has a certain authority over an account, by requesting to decode a message
account
String Hive account to perform the requestmessage
String Message to be decoded by the accountkey
String Type of key. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the request
const keychain = window.hive_keychain;
keychain.requestVerifyKey('stoodkev', encodedMessage, 'Posting', (response) => {
if (response.success === true) {
const decodedMessage = response.result;
}
});
Requests a message to be signed with proper authority
account
String Hive account to perform the request. If null, user can choose the account from a dropdown (optional, defaultnull
)message
String Message to be signed by the accountkey
String Type of key. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)title
String Override "Sign message" title (optional, defaultnull
)
Requests to add account authority over another account. For more information about multisig, please read https://peakd.com/utopian-io/@stoodkev/how-to-set-up-and-use-multisignature-accounts-on-steem-blockchain
account
String Hive account to perform the requestauthorizedUsername
String Authorized accountrole
String Type of authority. Can be 'Posting','Active' or 'Memo'weight
number Weight of the authoritycallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Gives @stoodkev active authority with weight 2 to `account`
const keychain = window.hive_keychain
keychain.requestAddAccountAuthority(account, 'stoodkev', 'Active', 2, (response) => {
console.log(response);
});
Requests to remove an account authority over another account. For more information about multisig, please read https://peakd.com/utopian-io/@stoodkev/how-to-set-up-and-use-multisignature-accounts-on-steem-blockchain
account
String Hive account to perform the requestauthorizedUsername
String Account to lose authorityrole
String Type of authority. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Removes @stoodkev's active authority from `account`
const keychain = window.hive_keychain;
keychain.requestRemoveAccountAuthority(account, 'stoodkev', 'Active', (response) => {
console.log(response);
});
Requests to add a new key authority to an account. For more information about multisig, please read https://peakd.com/utopian-io/@stoodkev/how-to-set-up-and-use-multisignature-accounts-on-steem-blockchain
account
String Hive account to perform the requestauthorizedKey
String New public key to be associated with the accountrole
String Type of authority. Can be 'Posting','Active' or 'Memo'weight
number Weight of the key authoritycallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
const keychain = window.hive_keychain;
keychain.requestAddKeyAuthority(username, publicKey, 'Memo', 1, (response) => {
console.log(response);
});
Requests to remove a key to an account. For more information about multisig, please read https://peakd.com/utopian-io/@stoodkev/how-to-set-up-and-use-multisignature-accounts-on-steem-blockchain
account
String Hive account to perform the requestauthorizedKey
String Key to be removed (public key).role
String Type of authority. Can be 'Posting','Active' or 'Memo'.callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
const keychain = window.hive_keychain;
keychain.requestRemoveKeyAuthority(username, publicKey, 'Memo', (response) => {
console.log(response);
});
Generic broadcast request
account
String Hive account to perform the requestoperations
Array Array of operations to be broadcastedkey
String Type of key. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
const keychain = window.hive_keychain;
keychain.requestBroadcast('npfedwards', [
[
'account_witness_vote',
{
account: 'npfedwards',
witness: 'stoodkev',
approve: true
}
]
], 'Active', (response) => {
console.log(response);
});
Requests to sign a transaction with a given authority
account
String Hive account to perform the requesttx
Object Unsigned transactionkey
String Type of key. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// This example would be done much easier with requestBroadcast
import dhive from '@hiveio/dhive';
const client = new dhive.Client(['https://api.hive.blog', 'https://anyx.io', 'https://api.openhive.network']);
const keychain = window.hive_keychain;
const props = await client.database.getDynamicGlobalProperties();
const headBlockNumber = props.head_block_number;
const headBlockId = props.head_block_id;
const expireTime = 600000;
const op = {
ref_block_num: headBlockNumber & 0xffff,
ref_block_prefix: Buffer.from(headBlockId, 'hex').readUInt32LE(4),
expiration: new Date(Date.now() + expireTime).toISOString(),
operations: [...] // Add operations here
};
keychain.requestSignTx(username, op, 'Posting', async (response) => {
if (!response.error) {
console.log(response.result);
await client.database.verifyAuthority(response.result);
await client.broadcast.send(response.result);
}
});
Requests a signed call
account
String Hive account to perform the requestmethod
String Method of the callparams
String Parameters of the callkey
String Type of key. Can be 'Posting','Active' or 'Memo'callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
Meta
- deprecated: This is deprecated.
Requests to broadcast a blog post/comment
account
String Hive account to perform the requesttitle
String Title of the blog postbody
String Content of the blog postparent_perm
String Permlink of the parent post. Main tag for a root postparent_account
String Author of the parent post. Pass null for root postjson_metadata
Object Parameters of the callpermlink
String Permlink of the blog postcomment_options
Object Options attached to the blog post. Consult Hive documentation at https://developers.hive.io/apidefinitions/#broadcast_ops_comment_options to learn more about itcallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
const keychain = window.hive_keychain;
keychain.requestPost('stoodkev', 'Hello World!', '## This is a blog post \
\
And this is some text', 'Blog', null, {format:'markdown',description:'A blog post',tags:['Blog']},'hello-world', {"author":"stoodkev","permlink":"hi","max_accepted_payout":"100000.000 SBD","percent_steem_dollars":10000,"allow_votes":true,"allow_curation_rewards":true,"extensions":[[0,{"beneficiaries":[{"account":"yabapmatt","weight":1000},{"account":"steemplus-pay","weight":500}]}]]}, (response) => {
console.log(response);
});
Requests a vote
account
String Hive account to perform the requestpermlink
String Permlink of the blog postauthor
String Author of the blog postweight
Number Weight of the vote, comprised between -10,000 (-100%) and 10,000 (100%)callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Upvote with 50% weight
const keychain = window.hive_keychain;
keychain.requestVote('npfedwards', 'hello-world', 'stoodkev', 5000, (response) => {
console.log(response);
});
Requests a custom JSON broadcast
account
String Hive account to perform the request. If null, user can choose the account from a dropdown (optional, defaultnull
)id
String Type of custom_json to be broadcastedkey
String Type of key. Can be 'Posting','Active' or 'Memo'json
String Stringified custom jsondisplay_msg
String Message to display to explain to the user what this broadcast is aboutcallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
const keychain = window.hive_keychain;
keychain.requestCustomJson(null, 'sm_market_rent', 'Active', JSON.stringify({items:["9292cd44ccaef8b73a607949cc787f1679ede10b-93"],currency:"DEC",days:1}), 'Rent 1 card on Splinterlands', (response) => {
console.log(response);
});
Requests a transfer
account
String Hive account to perform the requestto
String Hive account to receive the transferamount
String Amount to be transfered. Requires 3 decimals.memo
String The memo will be automatically encrypted if starting by '#' and the memo key is available on Keychain. It will also overrule the account to be enforced, regardless of the 'enforce' parametercurrency
String 'HIVE' or 'HBD'callback
requestCallback Function that handles Keychain's response to the requestenforce
boolean If set to true, user cannot chose to make the transfer from another account (optional, defaultfalse
)rpc
String Override user's RPC settings (optional, defaultnull
)
const keychain = window.hive_keychain;
keychain.requestTransfer(username, toUsername, amount.toFixed(3),'','HIVE',(response) => {
console.log(response)
}, true);
Requests a token transfer
account
String Hive account to perform the requestto
String Hive account to receive the transferamount
String Amount to be transferred. Requires 3 decimals.memo
String Memo attached to the transfercurrency
String Token to be sentcallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestSendToken(username, toUsername, amount.toFixed(3), memo, 'DEC', (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Requests a delegation broadcast
username
String Hive account to perform the request. If null, user can choose the account from a dropdown (optional, defaultnull
)delegatee
String Account to receive the delegationamount
String Amount to be transfered. Requires 3 decimals for HP, 6 for VESTS.unit
String HP or VESTScallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestDelegation(null, 'stoodkev', '1.000', 'HP', (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Requests a witness vote broadcast
username
String Hive account to perform the request. If null, user can choose the account from a dropdown (optional, defaultnull
)witness
String Account to receive the witness votevote
boolean Set to true to vote for the witness, false to unvotecallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Unvote our witness vote for @stoodkev
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestWitnessVote(null, 'stoodkev', false, (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Select an account as proxy
username
String Hive account to perform the request. If null, user can choose the account from a dropdown (optional, defaultnull
)proxy
String Account to become the proxy. Empty string ('') to remove a proxycallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Let @stoodkev use our voting power in governance votes
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestProxy(null, 'stoodkev', (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
// Remove voting proxy
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestProxy(null, '', (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Request a power up
username
String Hive account to perform the requestrecipient
String Account to receive the power uphive
String Amount of HIVE to be powered upcallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Power up 5 HP
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestPowerUp(username, username, '5.000', (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Request a power down
username
String Hive account to perform the requesthive_power
String Amount of HIVE to be powered downcallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Power down 5 HP
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestPowerDown(username, '5.000', (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Request the creation of an account using claimed tokens
username
String Hive account to perform the requestnew_account
String New account to be createdowner
object owner authority objectactive
object active authority objectposting
object posting authority objectmemo
String public memo keycallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
Request the creation of a DHF proposal
username
String Hive account to perform the requestreceiver
String Account receiving the funding if the proposal is votedsubject
String Title of the DAOpermlink
String Permlink to the proposal descriptiondaily_pay
String Daily amount to be received byreceiver
start
String Starting dateend
String Ending dateextensions
String Stringified Array of extensionscallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestCreateProposal('keychain', 'keychain', 'Hive Keychain development', 'hive-keychain-proposal-dhf-ran717', '10.000', '2022-03-22', '2023-03-21', JSON.stringify([]), (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Request the removal of a DHF proposal
username
String Hive account to perform the requestproposal_ids
String Stringified Array of ids of the proposals to be removedextensions
String Stringified Array of extensionscallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestRemoveProposal(username, JSON.stringify([216]), JSON.stringify([]), (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Vote/Unvote a DHF proposal
username
String Hive account to perform the requestproposal_ids
String Stringified Array of Ids of the proposals to be votedapprove
boolean Set to true to support the proposal, false to remove a voteextensions
String Stringified Array of extensionscallback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Approve a proposal
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestUpdateProposalVote(username, JSON.stringify([216]), true, JSON.stringify([]), (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
// Unapprove a proposal
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestUpdateProposalVote(username, JSON.stringify([216]), false, JSON.stringify([]), (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Add a new account to Keychain
username
String username of the account to be addedkeys
Object private keys of the account : {active:'...',posting:'...',memo:'...'}. At least one must be specified. Alternatively, authorized accounts can be specified with @${username}.callback
requestCallback Function that handles Keychain's response to the request
if (window.hive_keychain) {
const postingKey = '...';
const keychain = window.hive_keychain;
keychain.requestConversion(username, {
posting: postingKey
}, (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Request currency conversion
username
String Hive account to perform the requestamount
String amount to be converted.collaterized
Boolean true to convert HIVE to HBD. false to convert HBD to HIVE.callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Convert 5 HIVE to HBD
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestConversion(username, '5.000', true, (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Request recurrent transfer
username
String Hive account to perform the request (optional, defaultnull
)to
String Hive account receiving the transfers.amount
String amount to be sent on each execution.currency
String HIVE or HBD on mainnet.memo
String transfer memorecurrence
Number How often will the payment be triggered (in hours) - minimum 24.executions
Number The times the recurrent payment will be executed - minimum 2.callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Let's send @stoodkev 5 HIVE a day
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestConversion(null, 'stoodkev', '5.000', 'HIVE', memo, 24, 7, (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Request swap
username
String Hive account to perform the request (optional, defaultnull
)startToken
String Incoming tokenendToken
String Outgoing tokenamount
number Amount of tokens to be swappedslippage
number Max slippagesteps
Object Steps returned by KeychainSDK.swaps.getEstimation(), of type IStep[]callback
requestCallback Function that handles Keychain's response to the requestrpc
String Override user's RPC settings (optional, defaultnull
)
// Let's swap 5 HIVE to DEC
// Estimated steps can be obtained via KeychainSDK.swaps.getEstimation()
if (window.hive_keychain) {
const keychain = window.hive_keychain;
keychain.requestSwap('keychain', 'HIVE', 'DEC', 5, 1, estimatedSteps, (response) => {
console.log(response);
});
} else {
alert('You do not have hive keychain installed');
}
Type: Function
response
Object Keychain's response to the request