The extension inject contentscript with web3 provider variable: vizonator. Any action is passed to expansion executive logic, which checks saved rules to approve or refuse the action. If no rules was found for specific site — extension asks the user for approval.
This documentation mostly for javascript frontend developers.
Available operations
Types of operations: sign and execute operation, extension data, API.
Each operation requires several rules scope. If user checked to remember decision, extension save it to specific site.
- check vizonator variable
- get_account (extension data)
- get_settings (extension data)
- get_accounts (extension data)
- switch_account (extension data)
- import_account
- get_custom_account (API)
- get_account_history (API)
- get_accounts_on_sale (API)
- get_subaccounts_on_sale (API)
- account_metadata
- award
- fixed_award
- committee_vote_request
- custom
- delegate_vesting_shares
- passwordless_auth
- sign_data
- transfer
- transfer_to_vesting
- withdraw_vesting
- accountsChanged (event)
- Memo key encryption
- Prediction market operations
check_vizonator
Test vizonator variable before request any operations.
if(typeof vizonator !== "undefined"){
$(".vizonator_callback.test_check_vizonator").html("Vizonator initialized!");
}
else{
$(".vizonator_callback.test_check_vizonator").html("Vizonator NOT initialized...");
}Run exampleget_account
Rules scope: account
Retrieving current account information from extension: login, current energy, if memo and active private keys are filled.
vizonator.get_account(function(error,result){
let el=$(".vizonator_callback.test_get_account");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleget_settings
Rules scope: settings
Retrieving current settings from extension: energy step, default energy spend by award operation, dark mode, language.
vizonator.get_settings(function(error,result){
let el=$(".vizonator_callback.test_get_settings");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleget_accounts
Rules scope: accounts
Retrieving the list of accounts added to the extension session: logins, which one is current, and boolean flags of stored keys (regular, active, memo). Private keys never leave the extension — the answer contains none. Needed by dApps to show an account picker before switch_account. The list is returned in the order the accounts were added.
vizonator.get_accounts(function(error,result){
let el=$(".vizonator_callback.test_get_accounts");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleswitch_account
Rules scope: account_switch
Ask to make another account of the session the current one (a dApp takes the list from get_accounts and the user picks). The extension always shows the confirmation window: a site cannot switch the wallet silently even when other operations are already trusted for it, and the decision is not remembered (the account_switch rule is never saved). If the requested account is already current the answer comes at once, without a window. An unknown login is refused with unknown_account. Result: {login, switched}.
let account="on1x";//any login from the get_accounts list
vizonator.switch_account({account:account},function(error,result){
let el=$(".vizonator_callback.test_switch_account");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleimport_account
Rules scope: account
let account="invite";
let regular_key=false;
let active_key="5KcfoRuDfkhrLCxVcE9x51J6KN9aM9fpb78tLrvvFckxVV6FyFW";
let memo_key=false;
vizonator.import_account(account,regular_key,active_key,memo_key,function(error,result){
let el=$(".vizonator_callback.test_import_account");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleget_custom_account
Rules scope: account, api
API request for any VIZ account with custom protocol sequencer. If account is empty or boolean false — asks for user account.
let account="on1x";
let protocol="V";//can be empty
vizonator.get_custom_account(account,protocol,function(error,result){
let el=$(".vizonator_callback.test_get_custom_account");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleget_account_history
Rules scope: account, api
API request for operation history to any VIZ account. If account is empty or boolean false — asks for user account.
let account="on1x";
let from=-1;//from the latest activity
let limit=5;
vizonator.get_account_history(account,from,limit,function(error,result){
let el=$(".vizonator_callback.test_get_account_history");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleget_accounts_on_sale
Rules scope: account, api
let from=0;//from first entry
let limit=50;//max 1000
vizonator.get_accounts_on_sale(from,limit,function(error,result){
let el=$(".vizonator_callback.test_get_accounts_on_sale");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleget_subaccounts_on_sale
Rules scope: account, api
let from=0;//from first entry
let limit=50;//max 1000
vizonator.get_subaccounts_on_sale(from,limit,function(error,result){
let el=$(".vizonator_callback.test_get_subaccounts_on_sale");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampleaccount_metadata
Rules scope: meta, regular, account
Rewrite/update account metadata information. Usualy used to modify profile page (first - get metadata from blockchain, second - change it structure, third - write it on blockchain by this operation).
let metadata="{}";//be careful, this operation will be clear account metadata
vizonator.account_metadata({json:metadata},function(error,result){
let el=$(".vizonator_callback.test_account_metadata");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text("Result: "+JSON.stringify(result));
}
});Run exampleaward
Rules scope: award, regular
Additional properties: beneficiaries (structed as array of accounts with percent of received reward [{"account":"login1","weight":100},{"account":"login2","weight":200}]), custom_sequence (used by social gateways), force_memo_encoding (force encoding), optional_memo_encoding (0.81+, lets the user decide: the confirmation window shows a checkbox, checked by default; shown only when the signing account has a memo key).
Result contains object with approximate_amount property as decimial. It is approximate amount of social capital that has been awarded.
vizonator.award({receiver:"on1x",energy:500,memo:"Vizonator docs"},function(error,result){
let el=$(".vizonator_callback.test_award");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result));
}
});Run examplefixed_award
Rules scope: award, regular
Identical to award, difference in variable reward_amount and max_energy for a fixed reward.
vizonator.fixed_award({receiver:"on1x",reward_amount:"1.000 VIZ",max_energy:500,memo:"Vizonator docs"},function(error,result){
let el=$(".vizonator_callback.test_fixed_award");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result));
}
});Run examplecommittee_vote_request
Rules scope: committee, regular
Vote for active request in VIZ DAO. Param vote_percent can be in range from -10000 (-100.00%) to 10000 (100.00%).
vizonator.committee_vote_request({request_id:5,vote_percent:10000},function(error,result){
let el=$(".vizonator_callback.test_committee_vote_request");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text("Result: "+JSON.stringify(result));
}
});Run examplecustom
Rules scope: custom, protocol_*, regular*, active*
Post custom protocol json data in blockchain. Authority can be active or regular.
let authority_type="regular";//can be "active"
let protocol_id="test";
let json_data='{"hello":"world"}';
vizonator.custom({authority:authority_type,id:protocol_id,json:json_data},function(error,result){
let el=$(".vizonator_callback.test_custom");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text("Result: "+JSON.stringify(result));
}
});Run exampledelegate_vesting_shares
Rules scope: delegate, active
Delegate social capital to another account or undelegate. Influences the efficiency of awards and votes in DAO.
let amount="1.000000 SHARES";//"0.000000 SHARES" for undelegate
vizonator.delegate_vesting_shares({delegatee:"on1x",vesting_shares:amount},function(error,result){
let el=$(".vizonator_callback.test_delegate_vesting_shares");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text("Result: "+JSON.stringify(result));
}
});Run examplepasswordless_auth
Rules scope: auth, account, regular*, active*
Sign unique passwordless string for proof of authentification: domain:auth:account:authority:timestamp:nonce. Site that processing the signature verification must cache it with 2-minute expiration to block any other attempts from other sources (in case of a MITM attack).
Optional field domain (since version 0.77) — which domain the signature is asked for; without it your own host is signed, exactly as before (old calls keep working automatically). For http/https you may name your OWN host, and since 0.77 also your main domain: a page on app.example.com may sign for example.com, as both belong to the same owner. The window then shows an orange warning: the string goes to the main domain, not to the host the page is open on, and it is never approved silently (not even when other operations are trusted for the site). A main domain may not sign for a subdomain, and a subdomain may not sign for a neighbouring subdomain; on platforms that hand subdomains out to anyone (github.io, vercel.app and the like) the main domain is the subdomain itself, otherwise evil.github.io would sign for everyone at once. viz:// names (VIZ DNS) are allowed from any page, but such a name is never approved silently — the user sees both the domain and the account that signs.
Error codes: domain_mismatch — a foreign domain, a neighbouring subdomain, or a main domain instead of a subdomain was named; bad_domain — the scheme is neither http/https nor viz://; unknown_account / account_changed — the account is gone or was switched while the window was open; refuse — the site is refused by the auth rule; no key — the session holds no key of the requested authority.
let authority_type="regular";//can be "active"
/* domain необязателен: без него подпись делается за домен страницы (как раньше).
Свой хост можно назвать явно, имя viz://... — только после подтверждения пользователем. */
//let domain="hub.viz.world";//or "viz://on1x" for a VIZ DNS name
vizonator.passwordless_auth({authority:authority_type/*,domain:domain*/},function(error,result){
let el=$(".vizonator_callback.test_passwordless_auth");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run examplesign_data
Rules scope: sign, account, regular*, active*
Sign an arbitrary string with the account key (in contrast to passwordless_auth, where the string is built by the extension itself). Params: data (string to sign), authority (regular by default, can be active). Result: {account, signature, public_key}. Nothing is broadcast to the blockchain — the signature is only a proof for your backend, so the string must contain your own origin and a timestamp/nonce, otherwise the signature can be replayed.
let authority_type="regular";//can be "active"
let data_to_sign="hub.viz.world:inbox.list:"+Math.floor(Date.now()/1000);
vizonator.sign_data({authority:authority_type,data:data_to_sign},function(error,result){
let el=$(".vizonator_callback.test_sign_data");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text(JSON.stringify(result,null,2));
}
});Run exampletransfer
Rules scope: transfer, active
Ask user to transfer amount of viz. Can force encoding the memo (force_memo_encoding) or leave the choice to the user (optional_memo_encoding, 0.81+ — a checkbox in the confirmation window). The amount field is optional: omit it and the user types the amount in the confirmation window (checked against the balance).
let amount="0.001 VIZ";
let memo="Vizonator docs";
let force_encoding=false;//can be boolean true for force encoding by shared memo key
vizonator.transfer({to:"committee",amount:amount,memo,force_memo_encoding:force_encoding},function(error,result){
let el=$(".vizonator_callback.test_transfer");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text("Result: "+JSON.stringify(result));
}
});Run exampletransfer_to_vesting
Rules scope: vesting, active
Ask user to stake amount of viz to social capital.
vizonator.transfer_to_vesting({to:"committee",amount:"0.001 VIZ"},function(error,result){
let el=$(".vizonator_callback.test_transfer_to_vesting");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text("Result: "+JSON.stringify(result));
}
});Run examplewithdraw_vesting
Rules scope: vesting, active
Ask user to unstake amount of social capital to viz.
vizonator.withdraw_vesting({vesting_shares:"10.000000 SHARES"},function(error,result){
let el=$(".vizonator_callback.test_withdraw_vesting");//debug element
if(error){
el.text("Error: "+JSON.stringify(error));
}
else{
el.text("Result: "+JSON.stringify(result));
}
});Run exampleaccountsChanged
Rules scope: accounts
Account-change event: the extension tells the page that the current account has changed instead of making the page wait for its next request (get_account / get_accounts). Subscribe with vizonator.on("accountsChanged",callback), unsubscribe with vizonator.off("accountsChanged",callback) (without a callback it drops every handler of the event). The event fires both when the user switches the account in the extension popup and when a switch is approved through switch_account — including from another site.
Rule: accounts. The channel itself opens no window, but the data goes only to a site whose accounts rule is already approved: otherwise the event arrives with the no_rule error and the page gets neither a login nor a window. A stored refusal is honoured (refuse). The payload is the same snapshot as get_accounts: {current,accounts:[{login,current,regular,active,memo}]}, with no private keys in it.
The subscription lives as long as the page: after a reload the page has to subscribe again.
/* accountsChanged: the extension reports an account change by itself.
Data arrives only if the accounts rule is approved for the site,
otherwise error = "no_rule" (and no window is shown). */
vizonator.on("accountsChanged",function(error,result){
if(error){
console.log("accountsChanged: "+JSON.stringify(error));
return;
}
console.log("current account: "+result.current);//same snapshot as get_accounts
});Memo key encryption
Since version 0.74 a page can encrypt a message for another account and decrypt messages addressed to the current one with the memo key: vizonator.encrypt(data,callback) and vizonator.decrypt(data,callback).
The scheme is ECDH on secp256k1, the shared point is hashed with SHA-512 and its first 32 bytes are the AES-256-GCM key; the authentication tag is appended to the ciphertext, the nonce is 12 bytes. Both are transferred base64.
- Nothing is broadcast and nothing is signed — no transaction is built, the operation costs neither VIZ nor energy. The page never sees the memo key nor the shared secret, only ciphertext or plain text.
- The account is taken from the session. The optional
accountfield is a check, not a choice: another login there is refused withunknown_accountinstead of silently answering for the current user. - Rules scope is separate for each direction:
memo_crypto, encrypt, memoandmemo_crypto, decrypt, memo. Approving "write" for a site does not give it "read". - The limit is announced explicitly: 8 MB of characters per call (the sum of
ctfor a batch), above that the call is refused withtoo_largeand the number. Nothing is truncated silently — split on your side.
The answer is {success:true,result:…}: {ct,iv} for encrypt, the plain text for a single decrypt, an array of {id,ok,message|error} for a batch. An error is a code as a string.
The samples below are static: a round trip needs a counterparty public key and a stored letter, so there is nothing meaningful to run from this page.
encrypt
Rules scope: memo_crypto, encrypt, memo
Encrypt a message for the account whose memo public key is passed in to. Only key:"memo" is accepted, other key types are refused with bad_key_type. Both public key checksum flavours are accepted (the VIZ canonical RIPEMD-160 and the double SHA-256 used by VIZ Hub), the body is always verified as a curve point.
| Field | Type | Required |
|---|---|---|
account | string | no |
key | string | no |
to | string | yes |
message | string | yes |
//memo public key of the recipient, for example from get_custom_account().memo_key
let recipient_memo_public_key="VIZ...";
vizonator.encrypt({key:"memo",to:recipient_memo_public_key,message:"hello"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));//error code as a string
}
else{
console.log(result.result);//{ct,iv} — base64 ciphertext and 12-byte nonce
}
});decrypt
Rules scope: memo_crypto, decrypt, memo
Decrypt a message addressed to the current account. One letter: from (sender memo public key), ct, iv — the result is the plain text. A batch: items as an array of {id,from,ct,iv} — every item is answered on its own, one unreadable letter does not cancel the rest. A call-level error (no memo key in the session, user refusal, malformed batch) cancels the whole call.
| Field | Type | Required |
|---|---|---|
account | string | no |
key | string | no |
from | string | yes |
ct | string | yes |
iv | string | yes |
items | array | no |
vizonator.decrypt({key:"memo",from:sender_memo_public_key,ct:letter.ct,iv:letter.iv},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result.result);//plain text
}
});
//batch: one unreadable letter does not cancel the rest
vizonator.decrypt({key:"memo",items:[
{id:1,from:sender_memo_public_key,ct:letter1.ct,iv:letter1.iv},
{id:2,from:sender_memo_public_key,ct:letter2.ct,iv:letter2.iv}
]},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
result.result.forEach(function(item){
console.log(item.id,item.ok?item.message:item.error);
});
}
});Error codes
| Code | Meaning |
|---|---|
user_rejected | The user refused the request in the confirmation window. |
no_memo_key | There is no memo private key in the session for the current account. |
unknown_account | The account field names an account other than the current one. |
bad_key_type | key is not "memo". |
bad_public_key | to or from is not a valid public key. |
bad_ciphertext | Malformed call shape or an unreadable ct/iv (for a batch it is reported per item). |
auth_failed | The GCM tag did not match: the letter is not addressed to this account or it is damaged. |
too_large | More than 8 MB of characters in one call; the code carries the limit. |
Prediction market operations
Since version 0.73 the extension exposes all 23 broadcastable prediction market operations of the VIZ blockchain (HF14 / Onix). Every operation is called the same way: vizonator.pm_place_bet(data,callback).
Three rules that differ from the operations above:
- The account is never taken from the page. The extension fills the actor field of the operation with the current user, a site can only pass the operation fields.
- A missing required field is refused before the confirmation window is shown — money fields and identifiers are never defaulted to zero. Omitted optional fields are sent as their default value; for
pm_oracle_update, whose fields areoptional<>on the wire, an omitted field stays absent and means "leave as is". - The rules scope is granular:
prediction_market, <operation>, <authority>. Approvingpm_place_betfor a site does not approvepm_create_marketfor it.
All operations require the active key, except pm_dispute_vote (regular). If the session has no needed key, the call is refused right away.
Amounts are strings with a ticker: "1.000 VIZ". Time is a blockchain timestamp: "2026-12-31T12:00:00". The samples below are not runnable from this page on purpose — every one of them spends money.
- pm_oracle_register
- pm_oracle_update
- pm_create_market
- pm_oracle_accept_market
- pm_place_bet
- pm_commit_bet
- pm_reveal_bet
- pm_cancel_bet
- pm_add_liquidity
- pm_withdraw_liquidity
- pm_resolve_market
- pm_no_contest
- pm_dispute_create
- pm_dispute_vote
- pm_dispute_resolve
- pm_dispute_oracle_respond
- pm_unban
- pm_transfer_position
- pm_lazy_deposit
- pm_lazy_withdraw
- pm_leverage_open
- pm_leverage_close
- pm_leverage_convert
pm_oracle_register
Rules scope: prediction_market, pm_oracle_register, active
Register the account as an oracle: insurance deposit, fees, rules url and auto-accept policy for new markets.
Account field filled by the extension: owner
| Field | Type | Required |
|---|---|---|
insurance | asset | yes |
fee_percent | uint | no |
fixed_fee | asset | yes |
rules_url | string | no |
auto_accept_creator | string | no |
auto_accept_resolver | string | no |
auto_accept | bool | no |
vizonator.pm_oracle_register({insurance:"100.000 VIZ",fixed_fee:"1.000 VIZ"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_oracle_update
Rules scope: prediction_market, pm_oracle_update, active
Update oracle settings. Every field is optional: an omitted field is left as is, insurance_delta adds to (or subtracts from) the insurance deposit.
Account field filled by the extension: owner
| Field | Type | Required |
|---|---|---|
insurance_delta | optional | no |
fee_percent | optional | no |
fixed_fee | optional | no |
rules_url | optional | no |
auto_accept_creator | optional | no |
auto_accept_resolver | optional | no |
auto_accept | optional | no |
vizonator.pm_oracle_update({insurance_delta:"100.000 VIZ",fee_percent:200},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_create_market
Rules scope: prediction_market, pm_create_market, active
Create a market: oracle, outcomes, initial liquidity, fees, betting and result deadlines, dispute and penalty policy.
Account field filled by the extension: creator
| Field | Type | Required |
|---|---|---|
oracle | string | yes |
market_type | uint | no |
outcomes | array | yes |
url | string | no |
oracle_fee_percent | uint | no |
oracle_fixed_fee | asset | yes |
creator_fee_percent | uint | no |
liquidity_fee_percent | uint | no |
liquidity | asset | yes |
lmsr_b | int | no |
betting_expiration | time | yes |
result_expiration | time | yes |
time_penalty_type | uint | no |
time_penalty_value | uint | no |
penalty_curve_type | uint | no |
allow_early_resolution | bool | no |
allow_cancellation | bool | no |
allow_batch | bool | no |
allow_instant_bet | bool | no |
endogeneity_tier | uint | no |
dispute_mode | uint | no |
dispute_resolver | string | no |
dispute_penalty_percent | int | no |
metadata | string | no |
vizonator.pm_create_market({oracle:"polymarket",outcomes:["yes","no"],oracle_fixed_fee:"1.000 VIZ",liquidity:"100.000 VIZ",betting_expiration:"2026-12-31T12:00:00",result_expiration:"2026-12-31T12:00:00"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_oracle_accept_market
Rules scope: prediction_market, pm_oracle_accept_market, active
Oracle accepts (or refuses) to serve the market and pins its fee for it.
Account field filled by the extension: oracle
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
accept | bool | no |
oracle_fee_percent | uint | no |
oracle_fixed_fee | asset | yes |
vizonator.pm_oracle_accept_market({market_id:0,oracle_fixed_fee:"1.000 VIZ"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_place_bet
Rules scope: prediction_market, pm_place_bet, active
Place a bet: side (buy/sell), outcome index, amount and min_tokens as slippage protection.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
side | int | yes |
outcome_index | int | yes |
amount | asset | yes |
min_tokens | int | no |
mode | uint | no |
vizonator.pm_place_bet({market_id:0,side:0,outcome_index:0,amount:"1.000 VIZ"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_commit_bet
Rules scope: prediction_market, pm_commit_bet, active
Hidden bet, first phase: publish the hash of the bet and lock the escrow (commit-reveal).
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
commitment | string | yes |
escrow_amount | asset | yes |
no_reveal_fee_percent | uint | yes |
vizonator.pm_commit_bet({market_id:0,commitment:"<sha256 of the bet>",escrow_amount:"1.000 VIZ",no_reveal_fee_percent:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_reveal_bet
Rules scope: prediction_market, pm_reveal_bet, active
Hidden bet, second phase: reveal the bet and the salt matching the published hash.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
commit_id | int | yes |
side | int | yes |
outcome_index | int | yes |
amount | asset | yes |
salt | string | yes |
min_tokens | int | no |
vizonator.pm_reveal_bet({commit_id:0,side:0,outcome_index:0,amount:"1.000 VIZ",salt:"<random salt>"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_cancel_bet
Rules scope: prediction_market, pm_cancel_bet, active
Sell the position back to the curve before the market closes (if the market allows cancellation), min_return protects the price.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
bet_id | int | yes |
min_return | int | no |
vizonator.pm_cancel_bet({bet_id:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_add_liquidity
Rules scope: prediction_market, pm_add_liquidity, active
Add liquidity to the market curve and earn a share of the fees.
Account field filled by the extension: provider
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
amount | asset | yes |
vizonator.pm_add_liquidity({market_id:0,amount:"1.000 VIZ"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_withdraw_liquidity
Rules scope: prediction_market, pm_withdraw_liquidity, active
Withdraw liquidity before the betting is closed. The fee is paid at settlement, so an early exit returns the principal only.
Account field filled by the extension: provider
| Field | Type | Required |
|---|---|---|
liquidity_id | int | yes |
amount | asset | yes |
vizonator.pm_withdraw_liquidity({liquidity_id:0,amount:"1.000 VIZ"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_resolve_market
Rules scope: prediction_market, pm_resolve_market, active
Oracle publishes the outcome of the market with a link and a reason for the decision.
Account field filled by the extension: oracle
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
winning_outcome | int | yes |
decision_url | string | no |
decision_reason | string | no |
vizonator.pm_resolve_market({market_id:0,winning_outcome:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_no_contest
Rules scope: prediction_market, pm_no_contest, active
Oracle voids the market — every bet is refunded.
Account field filled by the extension: oracle
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
reason | string | no |
vizonator.pm_no_contest({market_id:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_dispute_create
Rules scope: prediction_market, pm_dispute_create, active
Dispute the published outcome within the grace window. Requires a deposit.
Account field filled by the extension: disputer
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
proposed_outcome | int | yes |
reason | string | no |
vizonator.pm_dispute_create({market_id:0,proposed_outcome:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_dispute_vote
Rules scope: prediction_market, pm_dispute_vote, regular
Vote in a dispute with your stake weight. The only operation signed with the regular key.
Account field filled by the extension: voter
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
vote_outcome | int | yes |
vote_percent | int | yes |
vizonator.pm_dispute_vote({market_id:0,vote_outcome:0,vote_percent:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_dispute_resolve
Rules scope: prediction_market, pm_dispute_resolve, active
The resolver of the dispute publishes the correct outcome, penalises the oracle and may ban the oracle or the creator.
Account field filled by the extension: resolver
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
correct_outcome | int | yes |
penalty_amount | asset | yes |
ban_oracle | bool | no |
ban_oracle_until | time | yes |
ban_creator | bool | no |
ban_creator_until | time | yes |
vizonator.pm_dispute_resolve({market_id:0,correct_outcome:0,penalty_amount:"1.000 VIZ",ban_oracle_until:"2026-12-31T12:00:00",ban_creator_until:"2026-12-31T12:00:00"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_dispute_oracle_respond
Rules scope: prediction_market, pm_dispute_oracle_respond, active
Oracle answers the dispute before the vote is finalised.
Account field filled by the extension: oracle
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
response | string | yes |
vizonator.pm_dispute_oracle_respond({market_id:0,response:"oracle answer"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_unban
Rules scope: prediction_market, pm_unban, active
Resolver lifts the ban from an oracle or a market creator.
Account field filled by the extension: resolver
| Field | Type | Required |
|---|---|---|
target | string | yes |
unban_oracle | bool | no |
unban_creator | bool | no |
vizonator.pm_unban({target:"on1x"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_transfer_position
Rules scope: prediction_market, pm_transfer_position, active
Transfer a bet position (fully or partially) to another account. Amount is in shares, not in whole tokens.
Account field filled by the extension: from
| Field | Type | Required |
|---|---|---|
bet_id | int | yes |
to | string | yes |
amount | int | yes |
memo | string | no |
vizonator.pm_transfer_position({bet_id:0,to:"on1x",amount:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_lazy_deposit
Rules scope: prediction_market, pm_lazy_deposit, active
Deposit into the lazy liquidity pool — a passive product that funds leveraged positions.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
amount | asset | yes |
vizonator.pm_lazy_deposit({amount:"1.000 VIZ"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_lazy_withdraw
Rules scope: prediction_market, pm_lazy_withdraw, active
Withdraw from the lazy pool. Emergency withdrawal is penalised on the rewards; if the pool has no free balance the payout is queued.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
shares | int | yes |
emergency | bool | no |
vizonator.pm_lazy_withdraw({shares:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_leverage_open
Rules scope: prediction_market, pm_leverage_open, active
Open a leveraged position: your collateral plus a loan from the lazy pool.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
market_id | int | yes |
outcome_index | int | yes |
collateral | asset | yes |
loan | asset | yes |
min_tokens | int | no |
max_slippage_percent | uint | no |
vizonator.pm_leverage_open({market_id:0,outcome_index:0,collateral:"1.000 VIZ",loan:"1.000 VIZ"},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_leverage_close
Rules scope: prediction_market, pm_leverage_close, active
Close a leveraged position and repay the loan.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
position_id | int | yes |
min_return | int | no |
vizonator.pm_leverage_close({position_id:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});pm_leverage_convert
Rules scope: prediction_market, pm_leverage_convert, active
Convert a leveraged position into a plain bet by paying off the loan.
Account field filled by the extension: account
| Field | Type | Required |
|---|---|---|
position_id | int | yes |
conversion_profit_cost | uint | no |
vizonator.pm_leverage_convert({position_id:0},function(error,result){
if(error){
console.log("Error: "+JSON.stringify(error));
}
else{
console.log(result);//{block_num,id,trx_num}
}
});