Docs
Library
Math

Math

Generally, all types that are usable in o1js are also usable out-of-the-box in protokit. But there are some caveats to dealing with bounded integers (UInt64, UInt32).

Integers

By default, o1js exposes two classes UInt64 and UInt32 to protect you from overflows that can happen if you use Field directly. Unfortunately, these don't work well with Protokit since they use the hard-failing o1js assertions instead of the protokit-specific assert. This leads to your application being non-complete and being unable to include failed transactions in settlements.

To overcome this, we created a number of classes in @proto-kit/library that handle all of that for you while providing the same interface as the vanilla variants.

  • UInt32
  • UInt64
  • UInt112
  • UInt224

In addition to the o1js methods, we implement the sqrtMod() and sqrtFloor() functions to help facilitate square-root calculations.

⚠️

Make sure to import from @proto-kit/library when using UInt32 and UInt64

Precision

Since we don't have access to real numbers, only integers, doing things like division might get tricky sometimes. That's why most other ecosystems have adapted precision based integers.

In our case, we use UInt112 as the primary precision type, holding 112 bits of integer. 112 bits is reasonably efficient for Kimchi range-checks and has more than enough room for 18-decimal precision.

We have created helpers to facilitate working with precisions in your runtime code: PrecisionUInt112 and PrecisionUInt224.

An example of how you can divide a UInt112 number x by a another number y of the same type:

const precision = UInt112.from(10n ** 18n);
 
function divide(x: UInt112, y: UInt112): UInt112 {
  return PrecisionUInt112.fromUInt112(x)
    .mulPrecision(precision)
    .divPrecision(y)
}

Since PrecisionUInt112 is a subclass of UInt112, we can use polymorphism when returning it.