Usage
Configure and interact with Magi in 5 minutes or less.
Instantiation
Create an instance of Magi. Returns a Magi object.
import { Magi } from '@aioha/magi'
const magi = new Magi()
Enums
- Wallet
- Asset
- KeyTypes
The Wallet enum exported are as follows:
export enum Wallet {
Hive = 'hive',
Ethereum = 'evm',
Bitcoin = 'btc',
ViewOnly = 'viewonly'
}
The Asset enum exported are as follows:
export enum Asset {
hive = 'hive',
hbd = 'hbd',
shbd = 'hbd_savings'
}
The KeyTypes enum exported are as follows:
export enum KeyTypes {
Posting = 'posting',
Active = 'active'
}
KeyTypes is only applicable for Hive wallets. Ethereum and Bitcoin wallets always sign with the account's key.
Register Wallets
Hive Wallet
Register a Hive wallet using an Aioha instance.
import { initAioha } from '@aioha/aioha'
const aioha = initAioha()
magi.setAioha(aioha)
Ethereum Wallet
Register an Ethereum wallet using a Viem wallet client.
import { createWalletClient, http } from 'viem'
const viemClient = createWalletClient({
account: '0xYourAddress',
transport: http('https://your-rpc-url')
})
magi.setViem(viemClient)
Bitcoin Wallet
Register a Bitcoin wallet by providing a BtcClient object. This is a minimal interface that any Bitcoin wallet can implement.
import { BtcClient } from '@aioha/magi'
The BtcClient interface:
interface BtcClient {
address: string
signMessage(message: string): Promise<string>
}
address— Bitcoin address (P2PKH1..., P2SH-P2WPKH3..., or P2WPKHbc1q...)signMessage— Signs a message string and returns a base64-encoded signature (BIP-137 or BIP-322)
Taproot (bc1p...) addresses are not currently supported.
magi.setBitcoin({
address: 'bc1qYourAddress',
signMessage: (msg) => myBtcWallet.signMessage(msg)
})
Example: Reown AppKit
If you use Reown AppKit with the Bitcoin adapter, you can create a BtcClient from the AppKit modal:
import { createAppKit } from '@reown/appkit'
import { BitcoinAdapter } from '@reown/appkit-adapter-bitcoin'
const bitcoinAdapter = new BitcoinAdapter({ projectId })
const modal = createAppKit({
adapters: [bitcoinAdapter],
// ...
})
// After wallet connection:
const provider = modal.getProvider('bip122')
magi.setBitcoin({
address: modal.getAddress(),
signMessage: (msg) => provider.signMessage({
message: msg,
address: modal.getAddress(),
protocol: 'ECDSA'
})
})
Example: UniSat
const unisat = window.unisat
const accounts = await unisat.requestAccounts()
magi.setBitcoin({
address: accounts[0],
signMessage: (msg) => unisat.signMessage(msg)
})
View-only Wallet
Register a view-only wallet by passing a prefixed DID. This lets you display an account's state without ever holding a signer — useful for dashboards, block explorers, or preview UIs.
// Hive account
magi.setViewOnly('hive:alice')
// Ethereum account
magi.setViewOnly('did:pkh:eip155:1:0xYourAddress')
// Bitcoin account
magi.setViewOnly('did:pkh:bip122:000000000019d6689c085ae165831e93:bc1qYourAddress')
The prefix determines the chain:
| Prefix | Chain |
|---|---|
hive: | Hive |
did:pkh:eip155:1: | Ethereum |
did:pkh:bip122:000000000019d6689c085ae165831e93: | Bitcoin |
Any other input throws an Error.
All signing and broadcast operations on a view-only wallet return an OperationError with code 4200 and the message Cannot sign or transact in view only mode. getUser(), isConnected(), and getWallet() work as usual.
Set Active Wallet
Set the wallet type to use for transactions. This must be called before performing any operations.
import { Wallet } from '@aioha/magi'
magi.setWallet(Wallet.Ethereum)
// or
magi.setWallet(Wallet.Hive)
// or
magi.setWallet(Wallet.Bitcoin)
// or
magi.setWallet(Wallet.ViewOnly)
Setters
Set Magi API
Set the Magi GraphQL API URL. An optional array of fallback API URLs may be provided.
magi.setApi('https://vsc.techcoderx.com/api/v1/graphql', [
'https://api.vsc.eco/api/v1/graphql',
'https://vsc.atexoras.com:2087/api/v1/graphql'
])
The URL must start with http:// or https://. The default API is https://vsc.techcoderx.com/api/v1/graphql with built-in fallback nodes.
Set Network ID
Set the Magi network ID. Defaults to vsc-mainnet.
magi.setNetId('vsc-mainnet')
// For testnet
magi.setNetId('vsc-testnet')
Getters
Get API
Returns an array of API endpoints, where the first item is the main endpoint and the remaining are fallbacks.
magi.getApi() // ['https://vsc.techcoderx.com/api/v1/graphql', ...]
Get Network ID
Returns the current Magi network ID.
magi.getNetId() // 'vsc-mainnet'
Get Connected User
Returns the connected user address, or undefined if not connected.
// Without prefix
magi.getUser() // 'alice', '0xYourAddress', or 'bc1q...'
// With prefix
magi.getUser(true)
// 'hive:alice'
// 'did:pkh:eip155:1:0xYourAddress'
// 'did:pkh:bip122:000000000019d6689c085ae165831e93:bc1q...'
Get Active Wallet
Returns the Wallet enum of the wallet type currently in use, or undefined if not set.
magi.getWallet() // Wallet.Hive, Wallet.Ethereum, Wallet.Bitcoin, or Wallet.ViewOnly
Is Connected
Returns a boolean of whether a wallet is connected.
magi.isConnected() // true or false
Sign and Broadcast Transaction
Sign and broadcast a Magi transaction consisting of one or more operations.
- Usage
- Result
const result = await magi.signAndBroadcastTx([
{
type: 'call',
payload: {
contract_id: 'vsc1BX9RbKJYAqSSZZzrGeBWyBZkG3ojTVPRoo',
action: 'dumpEnv',
payload: '',
rc_limit: 300,
intents: []
}
}
], KeyTypes.Active)
tx: Array ofMagiOperationobjectskeyType(optional):KeyTypes.ActiveorKeyTypes.Posting— only applicable for Hive wallets, defaults toKeyTypes.Active
{
"success": true,
"result": "bafyreib5af..."
}
success: Boolean of whether the transaction was signed and broadcasted successfullyerror: Error message, if anyresult: Transaction CID
Operations
The return value for these method calls will be equivalent to sign and broadcast transaction result above.
Call Contract
Call a Magi smart contract.
// Call testLog at contract vsc1Bp8y... with 100 RC limit, no intents
const result = await magi.call('vsc1Bp8ykBKDT74vYrZShhfEhp8Mn8bG2ChiAf', 'testLog', { foo: 'bar' }, 100, [])
// With posting key (Hive wallets only)
const result = await magi.call('vsc1Bp8ykBKDT74vYrZShhfEhp8Mn8bG2ChiAf', 'testLog', { foo: 'bar' }, 100, [], KeyTypes.Posting)
contractId: The contract IDaction: The contract action/method to callpayload: The payload to pass to the contract actionrc_limit: The maximum RC (resource credits) to spend on this callintents: Array of transaction intentskeyType(optional): Key type for Hive wallets
Transfer
Transfer tokens to another Magi account.
// Transfer 1 HIVE to a Hive account
const xfer = await magi.transfer('hive:bob', 1, Asset.hive)
// Transfer 1 HBD to an Ethereum address with memo
const xferWithMemo = await magi.transfer('did:pkh:eip155:1:0xRecipient', 1, Asset.hbd, 'Optional memo')
to: Recipient address (prefixed withhive:,did:pkh:eip155:1:, ordid:pkh:bip122:...:)amount: Amount to transfer (must be greater than 0)currency:Asset.hiveorAsset.hbdmemo(optional): Transfer memo
Unmap
Unmap tokens from Magi.
// Unmap 1 HIVE
const wd = await magi.unmap('hive:charlie', 1, Asset.hive)
// Unmap 50 HBD with memo
const wdWithMemo = await magi.unmap('hive:charlie', 50, Asset.hbd, 'Optional memo')
to: Destination address on L1 (prefixed withhive:,did:pkh:eip155:1:, ordid:pkh:bip122:...:)amount: Amount to withdraw (must be greater than 0)currency:Asset.hiveorAsset.hbdmemo(optional): Withdrawal memo
Stake
Stake tokens on Magi.
import { VscStakeType } from '@aioha/aioha'
// Stake 2,000 HIVE for consensus (to self)
const consensusStake = await magi.stake(VscStakeType.Consensus, 2000)
// Stake 2,000 HIVE for consensus to another account
const consensusStakeOther = await magi.stake(VscStakeType.Consensus, 2000, 'hive:anotheraccount')
// Stake 100 HBD
const hbdStake = await magi.stake(VscStakeType.HBD, 100)
stakeType:VscStakeType.Consensusfor HIVE consensus staking,VscStakeType.HBDfor HBD stakingamount: Amount to stake (must be greater than 0)to(optional): Recipient address — defaults to the connected accountmemo(optional): Stake memo
Unstake
Unstake tokens on Magi.
import { VscStakeType } from '@aioha/aioha'
// Unstake 2,000 HIVE from consensus
const consensusUnstake = await magi.unstake(VscStakeType.Consensus, 2000)
// Unstake 100 HBD
const hbdUnstake = await magi.unstake(VscStakeType.HBD, 100)
stakeType:VscStakeType.Consensusfor HIVE consensus unstaking,VscStakeType.HBDfor HBD unstakingamount: Amount to unstake (must be greater than 0)to(optional): Recipient address — defaults to the connected accountmemo(optional): Unstake memo
Events
Subscribe to Magi events using the on, once, and off methods.
Subscribe
magi.on('wallet_changed', () => {
console.log('Wallet type changed to:', magi.getWallet())
})
magi.on('sign_tx_request', () => {
console.log('Transaction signature requested')
})
Subscribe Once
The listener will be called only on the next emission of the event.
magi.once('sign_tx_request', () => {
console.log('This fires only once')
})
Unsubscribe
const handler = () => console.log('wallet changed')
magi.on('wallet_changed', handler)
// Unsubscribe specific listener
magi.off('wallet_changed', handler)
// Unsubscribe all listeners for the event
magi.off('wallet_changed')
Event Reference
| Event | Description |
|---|---|
wallet_changed | Emitted when the active wallet type is changed via setWallet(), or when setViewOnly() updates the DID while Wallet.ViewOnly is the active wallet |
sign_tx_request | Emitted when a transaction signature is requested from the wallet |