Mivora developers

Mivora Vault

On-chain collateral for exchangers and sellers. Each member locks funds in a vault they cannot empty alone, and can only take tickets or orders covered by that collateral. If a member scams a customer, the server owner refunds the customer straight from the vault.

How it works

1

The exchanger runs /vault deposit on your server and taps the button. After they confirm in the Mivora app, the vault is created and tied to their Discord account, proven by a signature from the vault key.

2

They send their collateral (LTC or BTC) to the vault address, from any wallet. It counts once confirmed on the blockchain.

3

When they press Claim on a ticket, your bot calls Mivora with the amount the customer entered. Mivora reads the vault balance on the blockchain and reserves the amount only if it is covered.

4

When the ticket ends, your bot releases the amount. If there is a dispute, it stays locked until your decision.

Example: with 200 EUR of collateral, an exchanger can claim one 200 EUR ticket, or several tickets that add up to 200 EUR at most. A 120 EUR ticket leaves 80 EUR available until it is completed.

Who controls the funds

Who signsWhat happens
The exchanger aloneNothing moves. They cannot withdraw their collateral to run away.
The server owner aloneRefunds a scammed customer, or gives the collateral back when the exchanger leaves.
The exchanger, after 180 days without movementRecovers the vault alone, so funds are never stuck if the owner disappears.

These rules are written in the vault address itself (Bitcoin script). Mivora never holds a key and cannot move any funds. The owner signs refunds in the Mivora app, with the keys of their own wallet.

The owner can move the collateral alone: exchangers must trust the server owner, as with any deposit held by a server. Write your refund rules down and share them with your exchangers.

Collateral value

The vault balance is converted to your currency at the live price, with a safety margin against price drops: LTC counts for 70% of its value, BTC for 80%. Only confirmed funds count. Unconfirmed deposits are ignored until they confirm.

Two kinds of partners

TypeMembersWhat the collateral covers
ExchangeExchangersTickets they claim. The customer enters the amount when opening the ticket.
ShopSellersOrders they take. Use the order ID as ticket and the order total as amount.

The API is the same for both: reserve when a member takes a ticket or an order, release when it ends, lock it during a dispute.

Getting started

1

The Mivora team names the owner of your partnership (any member of your staff, not necessarily the server owner).

2

The owner adds the Mivora bot to the server (it needs the Manage Roles permission, with its role above the verified role), then runs /vault setup: type (Exchange or Shop), verified role, minimum collateral and currency. Only the owner named by the Mivora team can run it, with the Manage Server permission. It also posts a public Protected by Mivora Vault panel in the channel you choose, which shows your verified members and the collateral locked. Keeping it visible is part of the free partnership.

3

The bot gives a button that opens the Mivora app with a code (or open Shield, then Collateral vault, and enter the code). After the owner confirms: their owner keys are linked by signature and the partner API key (mvp_...) appears, shown once.

4

Give the key to your bot developer. Keep it on your bot's server, never in a public repository. /vault apikey creates a new one and disables the old one. /vault setup can be run again at any time to change the role, minimum or currency.

Required ticket rules

The collateral only protects customers if nobody can deal with them outside a claim. Every partner bot must follow these rules:

1

A Claim button on every ticket or order. It calls vault.claim and only assigns the ticket if Mivora accepts it.

2

No messages before the claim. Exchangers and sellers can see the ticket but cannot write in it (SendMessages denied for their role in the ticket channel).

3

Only the claimer talks to the customer. After a successful claim, give SendMessages to that member only. The others stay read-only, or lose access to the ticket.

Without these rules, a member could talk a customer into an exchange without claiming, and that exchange would not be covered by any collateral.

discord.js integration

Download mivora-vault.js (Node.js 18+, no dependencies) next to your bot, then:

const { MivoraVault } = require('./mivora-vault');
const vault = new MivoraVault(process.env.MIVORA_PARTNER_KEY);

// New ticket: exchangers can read it but cannot write until they claim
await channel.permissionOverwrites.edit(EXCHANGER_ROLE_ID, { ViewChannel: true, SendMessages: false });

// "Claim" button of a ticket
async function onClaim(interaction, ticket) {
  const r = await vault.claim(ticket.id, interaction.user.id, ticket.amount);
  if (!r.ok) return interaction.reply({ content: r.message, ephemeral: true });
  await interaction.channel.permissionOverwrites.edit(interaction.user.id, { ViewChannel: true, SendMessages: true });
  await assignTicket(ticket, interaction.user);
  await interaction.reply(`Claimed. ${r.available} ${r.currency.toUpperCase()} of collateral still available.`);
}

// Ticket closed
await vault.complete(ticket.id);          // exchange done
await vault.cancel(ticket.id);            // closed without an exchange
await vault.dispute(ticket.id);           // customer opened a dispute
await vault.resolve(ticket.id, 'refunded'); // owner refunded the customer from the vault
await vault.resolve(ticket.id, 'released'); // the exchanger was right

Every method returns { ok: true, ... } or { ok: false, reason, message }, where message is ready to show to the exchanger. Network errors never throw.

HTTP API

Base URL https://api.sovrawallet.eu, header authorization: Bearer mvp_..., JSON bodies. Amounts are in your currency (EUR by default).

RouteEffect
POST /v1/partners/claims
{"ticket":"42","exchanger":"<discord id>","amount":120}
Reserves the amount. 409 insufficient_collateral or 409 no_vault if it is not covered. Calling it again for the same ticket and exchanger is safe.
POST /v1/partners/claims/:ticket/completeExchange done, amount released.
POST /v1/partners/claims/:ticket/cancelTicket closed without an exchange, amount released.
POST /v1/partners/claims/:ticket/disputeDispute: the amount stays locked.
POST /v1/partners/claims/:ticket/resolve
{"outcome":"refunded"} or "released"
Dispute decided.
GET /v1/partners/exchangers/:discordIdCollateral, engaged, available, minimum, verified, vault addresses.

Responses include collateral, engaged, available, minimum, verified and currency. Two claims at the same time for the same exchanger are processed one after the other, so they can never exceed the collateral together.

Errors

CodeMeaning
401Missing or wrong partner key.
409 insufficient_collateralThe amount is not covered. The response gives available and engaged.
409 no_vaultThis Discord account has no linked vault. Ask the member to run /vault deposit.
429Too many requests: 300 claims per minute at most. Wait a moment and try again.

On Discord