Qubic QPI Language SupportVS Code extension providing language support for Qubic Smart Contracts written with the Qubic Public Interface (QPI).
FeaturesSyntax Highlighting
Snippets
Snippets are available in both Linter (Diagnostics)The extension analyses
The linter and validator run on file open, save, and every keystroke. Command: New Smart ContractCommand palette: Prompts for a contract name, generates a Usage Guide1. Install the ExtensionSearch for "Qubic QPI Language Support" in the VS Code Extensions panel ( 2. Create a New Smart ContractOpen the Command Palette (
Enter a contract name (letters, digits, underscores). The extension creates a ready-to-use 3. IntelliSense for
|
| Prefix | What it inserts |
|---|---|
qpi-contract |
Complete contract skeleton |
qpi-contract-doc |
JSDoc metadata block for AI coding agents |
qpi-procedure |
PUBLIC_PROCEDURE block |
qpi-function |
PUBLIC_FUNCTION block |
qpi-procedure-locals |
PUBLIC_PROCEDURE_WITH_LOCALS block |
qpi-function-locals |
PUBLIC_FUNCTION_WITH_LOCALS block |
qpi-epoch |
BEGIN_EPOCH / END_EPOCH block |
qpi-tick |
BEGIN_TICK / END_TICK block |
Snippets work in both qpi and cpp language modes.
6. Linter Warnings and Errors
The linter activates automatically for .h files that contain QPI keywords. Problems appear in the Problems panel (Ctrl+Shift+M) and as coloured underlines in the editor:
| Code | Colour | What to do |
|---|---|---|
QPI001 |
Yellow (Warning) for #include qpi.h only; red (Error) for any other # |
Remove all # before deploy; qpi.h is warning-level as a dev-only include |
QPI002 |
Red (Error) | Replace / with div(a, b) |
QPI003 |
Red (Error) | Replace % with mod(a, b) |
QPI004–QPI009, QPI013–QPI016 |
Red (Error) | Match the restriction named in the Problems panel message |
QPI008 |
Yellow (Warning) | Use :: only for contract types or QPI::… from qpi.h |
QPI010 |
Red (Error) | Add missing END_EPOCH after BEGIN_EPOCH |
QPI011 |
Red (Error) | Add missing END_TICK after BEGIN_TICK |
QPI012 |
Yellow (Warning) | Register the procedure/function (see Section 7) |
7. Contract Validator
The Contract Validator checks the overall structure of a QPI contract and catches mistakes that the line-level linter cannot see.
QPI010 — Missing END_EPOCH
Every BEGIN_EPOCH block must be closed with END_EPOCH. If the closing macro is absent the contract will not compile inside the Qubic node.
// Wrong — triggers QPI010
BEGIN_EPOCH
{
}
// END_EPOCH ← missing
// Correct
BEGIN_EPOCH
{
}
END_EPOCH
QPI011 — Missing END_TICK
Same rule as QPI010, but for tick hooks.
// Correct
BEGIN_TICK
{
}
END_TICK
QPI012 — Unregistered procedure or function
Every PUBLIC_PROCEDURE and PUBLIC_FUNCTION you declare must be listed inside the REGISTER_USER_FUNCTIONS_AND_PROCEDURES block. Omitting the registration means the Qubic network will never call your entry point.
// Declaration (triggers QPI012 if not registered below)
PUBLIC_PROCEDURE(Transfer)
{
// ...
}
// Registration block — Transfer must appear here
REGISTER_USER_FUNCTIONS_AND_PROCEDURES
{
REGISTER_USER_PROCEDURE(Transfer, 1); // ← required
}
The index (1, 2, …) is the call index used by clients to invoke the entry point. Each entry point needs a unique index.
Contract Metadata for AI Coding Agents
Add a JSDoc-style block directly above your contract struct to document it for AI coding agents (Copilot, Cursor, Claude, etc.) and developers:
/**
* @contract TransferContract
* @description Handles peer-to-peer QU transfers with optional escrow
* @author AndyQus
* @version 1
* @procedure Transfer — Transfers QU from caller to recipient
* @procedure Escrow — Holds QU in escrow until release condition is met
* @function GetBalance — Returns current contract balance
* @state transferCount — Number of successful transfers
*/
struct TransferContract : public ContractBase {
Use the qpi-contract-doc snippet to insert a pre-filled template.
Hover documentation: Hovering over the contract struct name shows the full metadata inline.
QPI017 validation: A Warning is emitted if a @procedure or @function is declared in the doc-comment but the corresponding PUBLIC_PROCEDURE(X) / PUBLIC_FUNCTION(X) is not found in the contract body.
QPI-Specific Rules
Preprocessor (#)
All preprocessor directives are prohibited in deployed contracts. For local development you may add #include "qpi.h" or #include <qpi.h> so IntelliSense understands QPI types; remove every # line before the contract is deployed. Use QPI built-in types and the qpi API object exclusively.
Integer Division and Modulo
The / and % operators are prohibited in QPI contracts (e.g. division by zero can yield inconsistent state). Always use:
div(dividend, divisor)instead ofa / b(returns zero if the divisor is zero)mod(dividend, divisor)instead ofa % b(returns zero if the divisor is zero)
div() and mod() are safe and valid
The linter flags raw / and % but does not flag div() or mod() — they are the required QPI idioms.
Supported QPI API (qpi.*)
Identity & Context
| Method | Description |
|---|---|
| invocator() | Returns the id of the direct caller of this contract invocation. |
| originator() | Returns the id of the originator of the transaction (the entity that signed it). |
| arbitrator() | Returns the id of the current arbitrator. |
| computor(index: uint16) | Returns the id of the computor at the given index (0–675). |
| isContractId(id: id) | Returns 1 if the given id belongs to a smart contract. |
Time
| Method | Description |
|---|---|
| tick() | Returns the current tick number of the Qubic network. |
| epoch() | Returns the current epoch number of the Qubic network. |
| year() | Returns the current UTC year offset (e.g. 25 for 2025). |
| month() | Returns the current UTC month (1–12). |
| day() | Returns the current UTC day of month (1–31). |
| hour() | Returns the current UTC hour (0–23). |
| minute() | Returns the current UTC minute (0–59). |
| second() | Returns the current UTC second (0–59). |
| millisecond() | Returns the current UTC millisecond (0–999). |
| dayOfWeek(year: uint8, month: uint8, day: uint8) | Returns the day of week for the given date (0 = Wednesday, ..., 6 = Tuesday). |
| now() | Returns the current date and time as a DateAndTime struct. |
Balance & Transfer
| Method | Description |
|---|---|
| transfer(dest: id, amount: sint64) | Transfers amount QU from this contract to dest. Returns false if the balance is insufficient. |
| burn(amount: sint64, contractIndexBurnedFor: uint32 = 0) | Burns amount QU permanently — removes them from circulation. Optional contractIndexBurnedFor defaults to 0 (this contract). Returns the amount burned or a negative value on error. |
| invocationReward() | Returns the amount of QU sent with the current invocation. |
| queryFeeReserve(contractIndex: uint32) | Returns the fee reserve of the contract at contractIndex (0 = this contract). |
| distributeDividends(amountPerShare: sint64) | Distributes amountPerShare QU to every shareholder of this contract. Returns 1 on success. |
Hashing & Crypto
| Method | Description |
|---|---|
| K12(data: T) | Computes the Qubic K12 hash of data and returns the result as an id. |
| signatureValidity(entity: id, digest: id, signature: Array<sint8, 64>) | Returns 1 if the signature is valid for the given entity and digest. |
| getPrevSpectrumDigest() | Returns the spectrum digest of the previous tick. |
| getPrevUniverseDigest() | Returns the universe digest of the previous tick. |
| getPrevComputerDigest() | Returns the computer digest of the previous tick. |
Spectrum / Entities
| Method | Description |
|---|---|
| getEntity(id: id, entity: Entity) | Fills entity with the spectrum entry for the given id. Returns 1 if found, 0 otherwise. |
| nextId(currentId: id) | Returns the next id in the spectrum after currentId. |
| prevId(currentId: id) | Returns the previous id in the spectrum before currentId. |
| numberOfTickTransactions() | Returns the number of transactions in the current tick. |
Assets
| Method | Description |
|---|---|
| issueAsset(name: uint64, numberOfDecimalPlaces: sint8, numberOfShares: sint64, unitOfMeasurement: uint64) | Issues a new asset on the Qubic network. Returns the number of issued shares, or a negative value on failure. |
| transferShareOwnershipAndPossession(assetName: uint64, issuer: id, owner: id, possessor: id, numberOfShares: sint64, newOwnerAndPossessor: id) | Transfers ownership and possession of numberOfShares asset shares from owner/possessor to newOwnerAndPossessor. Returns the number of transferred shares. |
| numberOfPossessedShares(assetName: uint64, issuer: id, owner: id, possessor: id, ownershipManagingContractIndex: uint32, possessionManagingContractIndex: uint32) | Returns the number of possessed shares matching all specified criteria. |
| numberOfShares(assetName: uint64, issuer: id) | Returns the total number of issued shares for the given asset. |
| isAssetIssued(issuer: id, assetName: uint64) | Returns 1 if the asset has been issued by the given issuer, 0 otherwise. |
| acquireShares(assetName: uint64, issuer: id, owner: id, possessor: id, numberOfShares: sint64, acquirerContractIndex: uint32) | Acquires shares into the contract. Returns the number of shares acquired, or a negative value on error. |
| releaseShares(assetName: uint64, issuer: id, owner: id, possessor: id, numberOfShares: sint64, releaserContractIndex: uint32) | Releases shares from the contract. Returns the number of shares released, or a negative value on error. |
| bidInIPO(ipoContractIndex: uint32, price: sint64, quantity: uint32) | Places an IPO bid. Returns the bid index or a negative value on error. |
| ipoBidId(ipoContractIndex: uint32, ipoBidIndex: uint32) | Returns the id of the bidder at the given IPO bid index. |
| ipoBidPrice(ipoContractIndex: uint32, ipoBidIndex: uint32) | Returns the bid price at the given IPO bid index. |
QPI Types
Common types used in QPI contracts:
| Type | Description |
|---|---|
Array<T, L> |
Fixed-size array — use instead of C++ arrays |
HashMap<K, V, L> |
Hash map with key K, value V, capacity L |
HashSet<K, L> |
Hash set with key K, capacity L |
Collection<T, L> |
Ordered collection with capacity L |
ContractState<T, N> |
Persistent contract state storage |
Entity |
Spectrum entry (public key + balance info) |
Asset |
Asset descriptor (issuer id + asset name) |
DateAndTime |
Date/time struct returned by qpi.now() |
NoData |
Empty struct for procedures/functions with no I/O |
id |
256-bit identity / address |
uint8 / uint16 / uint32 / uint64 / uint128 |
Unsigned integer types |
sint8 / sint16 / sint32 / sint64 |
Signed integer types |
bit |
Single-bit boolean (0 or 1) |
m256i |
256-bit value for digests and hashes |
Array typedefs |
bit_2…bit_4096, sint8_2…sint64_8, uint8_2…uint64_8, id_2/id_4/id_8 |
QPI Constants
Useful constants for QPI development:
| Constant | Value | Description |
|---|---|---|
NULL_ID |
id::zero() |
The zero/null identity |
NULL_INDEX |
-1 |
Invalid / not-found index sentinel |
NUMBER_OF_COMPUTORS |
676 |
Total computors in the network |
QUORUM |
451 |
Minimum computors required for consensus |
INVALID_AMOUNT |
— | Sentinel for invalid QU amounts |
_A – _Z |
letter values | Used with ID() macro to build identities from letters |
JANUARY – DECEMBER |
1–12 |
Month constants |
MONDAY – SUNDAY |
— | Day-of-week constants |
Screenshot

Requirements
- VS Code
^1.85.0 - No runtime dependencies
Building from Source
npm install
npm run compile
npm run package # produces .vsix
Install the .vsix via Extensions: Install from VSIX in VS Code.
Feature-Roadmap
Phase 1 - MVP (this release)
- [x] Syntax Highlighting (QPI keywords, macros, types)
- [x] Code Snippets (PUBLIC_PROCEDURE, PUBLIC_FUNCTION, contract skeleton)
- [x] Linter: QPI language restrictions (
#,/,%, pointers, native types, etc.) - [x] "New Qubic SC" template command
Phase 2 - Comfort
- [x] IntelliSense for all
qpi.*functions - [x] Hover documentation
- [x] Error squiggles (red underline for harder violations)
- [x] Full QPI type and constant completions (Array, HashMap, Entity, NULL_ID, etc.)
Phase 2.5 - AI Agent Support
- [x] JSDoc-style contract metadata (
@contract,@description,@procedure,@function,@state) - [x] Hover documentation from doc-comment metadata
- [x] QPI017 — warning when
@procedure/@functiondeclared but missing from code - [x]
qpi-contract-docsnippet
Phase 3 - Power
[ ] Dev Kit integration (deploy to testnet)
Note for contributors: This feature requires a stable Qubic CLI or REST API that allows contract developers to deploy
.hfiles to the Qubic testnet directly from VS Code. As of 2026-03, no such public API exists for contract developers — qubic-cli is targeted at node operators, not smart contract authors. If you know of an official deploy API or Dev Kit, please open an issue or contact the publisher.[x] Contract validator
Marketplace
Qubic QPI Language Support – VS Code Marketplace
Sources
Contributors
Thanks to everyone who has contributed code, fixes, and improvements to this extension.
- @double-k-3033 — Hardened smart contract detection
(
QPI_CONTRACT_DECLARATION_REGEX), split QPI001 into Warning/Error severity, and improved test harness accuracy. Thank you for the thorough and well-structured contributions!