Skip to content

Add fixed-point factories and guards#1561

Merged
lorisleiva merged 1 commit into
mainfrom
04-23-add_fixed-point_factories_and_guards
May 5, 2026
Merged

Add fixed-point factories and guards#1561
lorisleiva merged 1 commit into
mainfrom
04-23-add_fixed-point_factories_and_guards

Conversation

@lorisleiva
Copy link
Copy Markdown
Member

This PR is part of the stack implementing the fixed-point number types proposed in #1545. It adds the first runtime code on top of the type and error scaffolding from previous PRs.

Adds three curried factory families per kind (outer call validates the shape once, inner call constructs values):

  • decimalFixedPoint / binaryFixedPoint parse decimal strings.
  • rawDecimalFixedPoint / rawBinaryFixedPoint accept a pre-scaled raw bigint.
  • ratioDecimalFixedPoint / ratioBinaryFixedPoint construct from a numerator / denominator.
const usdc = decimalFixedPoint('unsigned', 64, 6);
usdc('42.5');                                        // raw === 42500000n
rawDecimalFixedPoint('unsigned', 64, 6)(42500000n);  // same value
ratioDecimalFixedPoint('unsigned', 64, 6)(1n, 4n);   // 0.25

Factories default to 'strict' rounding and throw when inputs can't be represented exactly. Pass 'floor', 'ceil', 'trunc', or 'round' to opt into lossy construction. Invalid shape parameters, out-of-range raw values, zero denominators, and malformed strings throw their respective FIXED_POINTS error codes. All constructed values are Object.freeze-d.

const q1_15 = binaryFixedPoint('signed', 16, 15);
q1_15('0.5');           // raw === 16384n (exact)
q1_15('0.1');           // throws STRICT_MODE_PRECISION_LOSS
q1_15('0.1', 'round');  // raw === 3277n

Also adds isBinaryFixedPoint / assertIsBinaryFixedPoint and decimal equivalents. Each shape parameter is independently optional; pass undefined to leave a field unconstrained. assertIs* is the source of truth and is* wraps it in try/catch.

if (isBinaryFixedPoint(value, 'signed', 16, 15)) {
    value satisfies BinaryFixedPoint<'signed', 16, 15>;
}
assertIsBinaryFixedPoint(value, 'signed'); // narrows to BinaryFixedPoint<'signed', number, number>

The @solana/fixed-points README will be written in one pass at the end of this stack, once the full public API is in place.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 24, 2026

⚠️ No Changeset found

Latest commit: b5dbd9e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@bundlemon
Copy link
Copy Markdown

bundlemon Bot commented Apr 24, 2026

BundleMon

Files updated (4)
Status Path Size Limits
fixed-points/dist/index.browser.mjs
2.25KB (+2.11KB +1499.31%) -
fixed-points/dist/index.node.mjs
2.25KB (+2.11KB +1531.21%) -
fixed-points/dist/index.native.mjs
2.25KB (+2.11KB +1509.09%) -
@solana/kit production bundle
kit/dist/index.production.min.js
49.2KB (+1.49KB +3.11%) -
Unchanged files (143)
Status Path Size Limits
errors/dist/index.node.mjs
20.44KB -
errors/dist/index.browser.mjs
20.42KB -
errors/dist/index.native.mjs
20.41KB -
rpc-graphql/dist/index.browser.mjs
18.82KB -
rpc-graphql/dist/index.native.mjs
18.81KB -
rpc-graphql/dist/index.node.mjs
18.81KB -
wallet-account-signer/dist/index.node.mjs
17.29KB -
wallet-account-signer/dist/index.browser.mjs
17.27KB -
wallet-account-signer/dist/index.native.mjs
17.27KB -
transaction-messages/dist/index.browser.mjs
11.32KB -
transaction-messages/dist/index.native.mjs
11.32KB -
transaction-messages/dist/index.node.mjs
11.32KB -
instruction-plans/dist/index.browser.mjs
6.58KB -
instruction-plans/dist/index.native.mjs
6.58KB -
instruction-plans/dist/index.node.mjs
6.58KB -
codecs-data-structures/dist/index.browser.mjs
5.04KB -
codecs-data-structures/dist/index.native.mjs
5.03KB -
codecs-data-structures/dist/index.node.mjs
5.03KB -
offchain-messages/dist/index.browser.mjs
4.89KB -
offchain-messages/dist/index.native.mjs
4.89KB -
offchain-messages/dist/index.node.mjs
4.89KB -
transactions/dist/index.browser.mjs
4.07KB -
transactions/dist/index.native.mjs
4.07KB -
transactions/dist/index.node.mjs
4.07KB -
kit/dist/index.browser.mjs
3.72KB -
kit/dist/index.native.mjs
3.72KB -
kit/dist/index.node.mjs
3.72KB -
codecs-core/dist/index.browser.mjs
3.62KB -
codecs-core/dist/index.native.mjs
3.62KB -
codecs-core/dist/index.node.mjs
3.62KB -
webcrypto-ed25519-polyfill/dist/index.node.mj
s
3.61KB -
webcrypto-ed25519-polyfill/dist/index.browser
.mjs
3.59KB -
webcrypto-ed25519-polyfill/dist/index.native.
mjs
3.57KB -
rpc-subscriptions/dist/index.browser.mjs
3.37KB -
rpc-subscriptions/dist/index.node.mjs
3.34KB -
rpc-subscriptions/dist/index.native.mjs
3.31KB -
signers/dist/index.browser.mjs
3.26KB -
signers/dist/index.native.mjs
3.26KB -
signers/dist/index.node.mjs
3.26KB -
rpc-transformers/dist/index.browser.mjs
3.16KB -
rpc-transformers/dist/index.native.mjs
3.16KB -
rpc-transformers/dist/index.node.mjs
3.16KB -
react/dist/index.browser.mjs
3.09KB -
react/dist/index.native.mjs
3.09KB -
react/dist/index.node.mjs
3.09KB -
keys/dist/index.node.mjs
3.06KB -
addresses/dist/index.browser.mjs
2.93KB -
addresses/dist/index.native.mjs
2.92KB -
addresses/dist/index.node.mjs
2.92KB -
keys/dist/index.browser.mjs
2.85KB -
keys/dist/index.native.mjs
2.85KB -
codecs-strings/dist/index.browser.mjs
2.55KB -
codecs-strings/dist/index.node.mjs
2.51KB -
codecs-strings/dist/index.native.mjs
2.47KB -
transaction-confirmation/dist/index.node.mjs
2.41KB -
sysvars/dist/index.browser.mjs
2.37KB -
sysvars/dist/index.native.mjs
2.37KB -
sysvars/dist/index.node.mjs
2.37KB -
transaction-confirmation/dist/index.native.mj
s
2.36KB -
transaction-confirmation/dist/index.browser.m
js
2.35KB -
rpc-subscriptions-spec/dist/index.node.mjs
2.21KB -
rpc-subscriptions-spec/dist/index.native.mjs
2.17KB -
rpc-subscriptions-spec/dist/index.browser.mjs
2.16KB -
subscribable/dist/index.node.mjs
1.97KB -
rpc/dist/index.node.mjs
1.95KB -
codecs-numbers/dist/index.browser.mjs
1.95KB -
codecs-numbers/dist/index.native.mjs
1.95KB -
codecs-numbers/dist/index.node.mjs
1.94KB -
subscribable/dist/index.native.mjs
1.92KB -
subscribable/dist/index.browser.mjs
1.91KB -
rpc-transport-http/dist/index.browser.mjs
1.91KB -
rpc-transport-http/dist/index.native.mjs
1.9KB -
rpc/dist/index.native.mjs
1.81KB -
rpc/dist/index.browser.mjs
1.8KB -
rpc-transport-http/dist/index.node.mjs
1.72KB -
rpc-types/dist/index.browser.mjs
1.53KB -
rpc-types/dist/index.native.mjs
1.53KB -
rpc-types/dist/index.node.mjs
1.53KB -
rpc-subscriptions-channel-websocket/dist/inde
x.node.mjs
1.33KB -
rpc-subscriptions-channel-websocket/dist/inde
x.native.mjs
1.27KB -
rpc-subscriptions-channel-websocket/dist/inde
x.browser.mjs
1.26KB -
program-client-core/dist/index.browser.mjs
1.21KB -
program-client-core/dist/index.native.mjs
1.21KB -
program-client-core/dist/index.node.mjs
1.21KB -
options/dist/index.browser.mjs
1.18KB -
options/dist/index.native.mjs
1.18KB -
options/dist/index.node.mjs
1.17KB -
accounts/dist/index.browser.mjs
1.17KB -
accounts/dist/index.native.mjs
1.17KB -
accounts/dist/index.node.mjs
1.16KB -
rpc-api/dist/index.browser.mjs
976B -
rpc-api/dist/index.native.mjs
975B -
rpc-api/dist/index.node.mjs
973B -
compat/dist/index.browser.mjs
969B -
compat/dist/index.native.mjs
968B -
compat/dist/index.node.mjs
966B -
rpc-spec-types/dist/index.browser.mjs
962B -
rpc-spec-types/dist/index.native.mjs
961B -
rpc-spec-types/dist/index.node.mjs
959B -
rpc-subscriptions-api/dist/index.native.mjs
870B -
rpc-subscriptions-api/dist/index.node.mjs
869B -
rpc-subscriptions-api/dist/index.browser.mjs
868B -
rpc-spec/dist/index.browser.mjs
852B -
rpc-spec/dist/index.native.mjs
851B -
rpc-spec/dist/index.node.mjs
850B -
promises/dist/index.native.mjs
841B -
promises/dist/index.node.mjs
840B -
promises/dist/index.browser.mjs
839B -
plugin-core/dist/index.browser.mjs
820B -
plugin-core/dist/index.native.mjs
819B -
plugin-core/dist/index.node.mjs
817B -
assertions/dist/index.browser.mjs
783B -
instructions/dist/index.browser.mjs
771B -
instructions/dist/index.native.mjs
770B -
instructions/dist/index.node.mjs
768B -
fast-stable-stringify/dist/index.browser.mjs
726B -
fast-stable-stringify/dist/index.native.mjs
725B -
assertions/dist/index.native.mjs
724B -
fast-stable-stringify/dist/index.node.mjs
724B -
assertions/dist/index.node.mjs
723B -
programs/dist/index.browser.mjs
329B -
programs/dist/index.native.mjs
327B -
programs/dist/index.node.mjs
325B -
fs-impl/dist/index.browser.mjs
245B -
event-target-impl/dist/index.node.mjs
230B -
functional/dist/index.browser.mjs
154B -
functional/dist/index.native.mjs
152B -
text-encoding-impl/dist/index.native.mjs
152B -
functional/dist/index.node.mjs
151B -
codecs/dist/index.browser.mjs
145B -
codecs/dist/index.native.mjs
144B -
codecs/dist/index.node.mjs
142B -
event-target-impl/dist/index.browser.mjs
133B -
ws-impl/dist/index.node.mjs
131B -
text-encoding-impl/dist/index.browser.mjs
122B -
fs-impl/dist/index.node.mjs
120B -
text-encoding-impl/dist/index.node.mjs
119B -
ws-impl/dist/index.browser.mjs
113B -
crypto-impl/dist/index.node.mjs
111B -
crypto-impl/dist/index.browser.mjs
109B -
rpc-parsed-types/dist/index.browser.mjs
66B -
rpc-parsed-types/dist/index.native.mjs
65B -
rpc-parsed-types/dist/index.node.mjs
63B -

Total files change +7.81KB +1.56%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Documentation Preview: https://kit-docs-hck5tumxo-anza-tech.vercel.app

@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_factories_and_guards branch from a7240d5 to f32b052 Compare April 24, 2026 16:17
@lorisleiva lorisleiva requested a review from mcintyre94 April 24, 2026 16:38
@lorisleiva lorisleiva marked this pull request as ready for review April 24, 2026 16:38
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_factories_and_guards branch from f32b052 to ab5d757 Compare April 29, 2026 00:30
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_types branch from 17de005 to 2ef4868 Compare April 29, 2026 00:30
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_types branch from 2ef4868 to f04b24e Compare May 4, 2026 03:59
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_factories_and_guards branch 2 times, most recently from 8cf3251 to b713946 Compare May 5, 2026 11:17
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_types branch from 29d9851 to aa0861a Compare May 5, 2026 13:51
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_factories_and_guards branch from b713946 to 05fd721 Compare May 5, 2026 13:51
@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 5, 2026

Copy link
Copy Markdown
Member Author

lorisleiva commented May 5, 2026

Merge activity

  • May 5, 8:27 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 5, 8:48 PM UTC: Graphite couldn't merge this pull request because a downstack PR Add fixed-point types #1560 failed to merge.
  • May 5, 9:18 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 5, 9:18 PM UTC: @lorisleiva merged this pull request with Graphite.

@lorisleiva lorisleiva changed the base branch from 04-23-add_fixed-point_types to graphite-base/1561 May 5, 2026 20:40
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_factories_and_guards branch from 05fd721 to f60f33b Compare May 5, 2026 20:53
@lorisleiva lorisleiva force-pushed the graphite-base/1561 branch from aa0861a to b015176 Compare May 5, 2026 20:53
@lorisleiva lorisleiva changed the base branch from graphite-base/1561 to 04-23-add_fixed-point_types May 5, 2026 20:53
Base automatically changed from 04-23-add_fixed-point_types to main May 5, 2026 20:54
This PR is part of the stack implementing the fixed-point number types proposed in #1545. It adds the first runtime code on top of the type and error scaffolding from previous PRs.

Adds three curried factory families per kind (outer call validates the shape once, inner call constructs values):

- `decimalFixedPoint` / `binaryFixedPoint` parse decimal strings.
- `rawDecimalFixedPoint` / `rawBinaryFixedPoint` accept a pre-scaled raw bigint.
- `ratioDecimalFixedPoint` / `ratioBinaryFixedPoint` construct from a `numerator / denominator`.

```ts
const usdc = decimalFixedPoint('unsigned', 64, 6);
usdc('42.5');                                        // raw === 42500000n
rawDecimalFixedPoint('unsigned', 64, 6)(42500000n);  // same value
ratioDecimalFixedPoint('unsigned', 64, 6)(1n, 4n);   // 0.25
```

Factories default to `'strict'` rounding and throw when inputs can't be represented exactly. Pass `'floor'`, `'ceil'`, `'trunc'`, or `'round'` to opt into lossy construction. Invalid shape parameters, out-of-range raw values, zero denominators, and malformed strings throw their respective `FIXED_POINTS` error codes. All constructed values are `Object.freeze`-d.

```ts
const q1_15 = binaryFixedPoint('signed', 16, 15);
q1_15('0.5');           // raw === 16384n (exact)
q1_15('0.1');           // throws STRICT_MODE_PRECISION_LOSS
q1_15('0.1', 'round');  // raw === 3277n
```

Also adds `isBinaryFixedPoint` / `assertIsBinaryFixedPoint` and decimal equivalents. Each shape parameter is independently optional; pass `undefined` to leave a field unconstrained. `assertIs*` is the source of truth and `is*` wraps it in `try/catch`.

```ts
if (isBinaryFixedPoint(value, 'signed', 16, 15)) {
    value satisfies BinaryFixedPoint<'signed', 16, 15>;
}
assertIsBinaryFixedPoint(value, 'signed'); // narrows to BinaryFixedPoint<'signed', number, number>
```

The `@solana/fixed-points` README will be written in one pass at the end of this stack, once the full public API is in place.
@lorisleiva lorisleiva force-pushed the 04-23-add_fixed-point_factories_and_guards branch from f60f33b to b5dbd9e Compare May 5, 2026 20:54
@lorisleiva lorisleiva merged commit cd61ce0 into main May 5, 2026
14 checks passed
@lorisleiva lorisleiva deleted the 04-23-add_fixed-point_factories_and_guards branch May 5, 2026 21:18
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

🔎💬 Inkeep AI search and chat service is syncing content for source 'Solana Kit Docs'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants