tigerbeetle-node 0.14.178 → 0.14.180

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/bindings.ts CHANGED
@@ -24,6 +24,11 @@ export enum AccountFlags {
24
24
  * See [credits_must_not_exceed_debits](https://docs.tigerbeetle.com/reference/accounts#flagscredits_must_not_exceed_debits)
25
25
  */
26
26
  credits_must_not_exceed_debits = (1 << 2),
27
+
28
+ /**
29
+ * See [history](https://docs.tigerbeetle.com/reference/accounts#flagshistory)
30
+ */
31
+ history = (1 << 3),
27
32
  }
28
33
 
29
34
 
@@ -66,23 +71,23 @@ export enum TransferFlags {
66
71
 
67
72
 
68
73
  /**
69
- * See [GetAccountTransfersFlags](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flags)
74
+ * See [AccountFilterFlags](https://docs.tigerbeetle.com/reference/account_filter#flags)
70
75
  */
71
- export enum GetAccountTransfersFlags {
76
+ export enum AccountFilterFlags {
72
77
  none = 0,
73
78
 
74
79
  /**
75
- * See [debits](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flagsdebits)
80
+ * See [debits](https://docs.tigerbeetle.com/reference/account_filter#flagsdebits)
76
81
  */
77
82
  debits = (1 << 0),
78
83
 
79
84
  /**
80
- * See [credits](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flagscredits)
85
+ * See [credits](https://docs.tigerbeetle.com/reference/account_filter#flagscredits)
81
86
  */
82
87
  credits = (1 << 1),
83
88
 
84
89
  /**
85
- * See [reversed](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flagsreversed)
90
+ * See [reversed](https://docs.tigerbeetle.com/reference/account_filter#flagsreversed)
86
91
  */
87
92
  reversed = (1 << 2),
88
93
  }
@@ -647,41 +652,74 @@ export type CreateTransfersError = {
647
652
 
648
653
 
649
654
  /**
650
- * See [GetAccountTransfers](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#)
655
+ * See [AccountFilter](https://docs.tigerbeetle.com/reference/account_filter#)
651
656
  */
652
- export type GetAccountTransfers = {
657
+ export type AccountFilter = {
653
658
 
654
659
  /**
655
- * See [account_id](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#account_id)
660
+ * See [account_id](https://docs.tigerbeetle.com/reference/account_filter#account_id)
656
661
  */
657
662
  account_id: bigint
658
663
 
659
664
  /**
660
- * See [timestamp_min](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#timestamp_min)
665
+ * See [timestamp_min](https://docs.tigerbeetle.com/reference/account_filter#timestamp_min)
661
666
  */
662
667
  timestamp_min: bigint
663
668
 
664
669
  /**
665
- * See [timestamp_max](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#timestamp_max)
670
+ * See [timestamp_max](https://docs.tigerbeetle.com/reference/account_filter#timestamp_max)
666
671
  */
667
672
  timestamp_max: bigint
668
673
 
669
674
  /**
670
- * See [limit](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#limit)
675
+ * See [limit](https://docs.tigerbeetle.com/reference/account_filter#limit)
671
676
  */
672
677
  limit: number
673
678
 
674
679
  /**
675
- * See [flags](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flags)
680
+ * See [flags](https://docs.tigerbeetle.com/reference/account_filter#flags)
676
681
  */
677
682
  flags: number
678
683
  }
679
684
 
685
+
686
+ /**
687
+ * See [AccountBalance](https://docs.tigerbeetle.com/reference/account_balances#)
688
+ */
689
+ export type AccountBalance = {
690
+
691
+ /**
692
+ * See [debits_pending](https://docs.tigerbeetle.com/reference/account_balances#debits_pending)
693
+ */
694
+ debits_pending: bigint
695
+
696
+ /**
697
+ * See [debits_posted](https://docs.tigerbeetle.com/reference/account_balances#debits_posted)
698
+ */
699
+ debits_posted: bigint
700
+
701
+ /**
702
+ * See [credits_pending](https://docs.tigerbeetle.com/reference/account_balances#credits_pending)
703
+ */
704
+ credits_pending: bigint
705
+
706
+ /**
707
+ * See [credits_posted](https://docs.tigerbeetle.com/reference/account_balances#credits_posted)
708
+ */
709
+ credits_posted: bigint
710
+
711
+ /**
712
+ * See [timestamp](https://docs.tigerbeetle.com/reference/account_balances#timestamp)
713
+ */
714
+ timestamp: bigint
715
+ }
716
+
680
717
  export enum Operation {
681
718
  create_accounts = 128,
682
719
  create_transfers = 129,
683
720
  lookup_accounts = 130,
684
721
  lookup_transfers = 131,
685
722
  get_account_transfers = 132,
723
+ get_account_history = 133,
686
724
  }
687
725
 
package/src/index.ts CHANGED
@@ -5,8 +5,10 @@ import {
5
5
  CreateAccountsError,
6
6
  CreateTransfersError,
7
7
  Operation,
8
- GetAccountTransfers,
8
+ AccountFilter,
9
+ AccountBalance,
9
10
  } from './bindings'
11
+ import { randomFillSync } from 'node:crypto'
10
12
 
11
13
  const binding: Binding = (() => {
12
14
  const { arch, platform } = process
@@ -66,8 +68,8 @@ const binding: Binding = (() => {
66
68
  export type Context = object // tb_client
67
69
  export type AccountID = bigint // u128
68
70
  export type TransferID = bigint // u128
69
- export type Event = Account | Transfer | AccountID | TransferID | GetAccountTransfers
70
- export type Result = CreateAccountsError | CreateTransfersError | Account | Transfer
71
+ export type Event = Account | Transfer | AccountID | TransferID | AccountFilter
72
+ export type Result = CreateAccountsError | CreateTransfersError | Account | Transfer | AccountBalance
71
73
  export type ResultCallback = (error: Error | null, results: Result[] | null) => void
72
74
 
73
75
  interface BindingInitArgs {
@@ -93,7 +95,8 @@ export interface Client {
93
95
  createTransfers: (batch: Transfer[]) => Promise<CreateTransfersError[]>
94
96
  lookupAccounts: (batch: AccountID[]) => Promise<Account[]>
95
97
  lookupTransfers: (batch: TransferID[]) => Promise<Transfer[]>
96
- getAccountTransfers: (filter: GetAccountTransfers) => Promise<Transfer[]>
98
+ getAccountTransfers: (filter: AccountFilter) => Promise<Transfer[]>
99
+ getAccountHistory: (filter: AccountFilter) => Promise<AccountBalance[]>
97
100
  destroy: () => void
98
101
  }
99
102
 
@@ -129,6 +132,49 @@ export function createClient (args: ClientInitArgs): Client {
129
132
  lookupAccounts(batch) { return request(Operation.lookup_accounts, batch) },
130
133
  lookupTransfers(batch) { return request(Operation.lookup_transfers, batch) },
131
134
  getAccountTransfers(filter) { return request(Operation.get_account_transfers, [filter]) },
135
+ getAccountHistory(filter) { return request(Operation.get_account_history, [filter]) },
132
136
  destroy() { binding.deinit(context) },
133
137
  }
134
138
  }
139
+
140
+ let idLastTimestamp = 0;
141
+ let idLastBuffer = new DataView(new ArrayBuffer(16));
142
+
143
+ /**
144
+ * Generates a Universally Unique and Sortable Identifier as a u128 bigint.
145
+ *
146
+ * @remarks
147
+ * Based on {@link https://github.com/ulid/spec}, IDs returned are guaranteed to be monotonically
148
+ * increasing.
149
+ */
150
+ export function id(): bigint {
151
+ // Ensure timestamp monotonically increases and generate a new random on each new timestamp.
152
+ let timestamp = Date.now()
153
+ if (timestamp <= idLastTimestamp) {
154
+ timestamp = idLastTimestamp
155
+ } else {
156
+ idLastTimestamp = timestamp
157
+ randomFillSync(idLastBuffer)
158
+ }
159
+
160
+ // Increment the u80 in idLastBuffer using carry arithmetic on u32s (as JS doesn't have fast u64).
161
+ const littleEndian = true
162
+ const randomLo32 = idLastBuffer.getUint32(0, littleEndian) + 1
163
+ const randomHi32 = idLastBuffer.getUint32(4, littleEndian) + (randomLo32 > 0xFFFFFFFF ? 1 : 0)
164
+ const randomHi16 = idLastBuffer.getUint16(8, littleEndian) + (randomHi32 > 0xFFFFFFFF ? 1 : 0)
165
+ if (randomHi16 > 0xFFFF) {
166
+ throw new Error('random bits overflow on monotonic increment')
167
+ }
168
+
169
+ // Store the incremented random monotonic and the timestamp into the buffer.
170
+ idLastBuffer.setUint32(0, randomLo32 & 0xFFFFFFFF, littleEndian)
171
+ idLastBuffer.setUint32(4, randomHi32 & 0xFFFFFFFF, littleEndian)
172
+ idLastBuffer.setUint16(8, randomHi16, littleEndian) // No need to mask since checked above.
173
+ idLastBuffer.setUint16(10, timestamp & 0xFFFF, littleEndian) // timestamp lo.
174
+ idLastBuffer.setUint32(12, (timestamp >>> 16) & 0xFFFFFFFF, littleEndian) // timestamp hi.
175
+
176
+ // Then return the buffer's contents as a little-endian u128 bigint.
177
+ const lo = idLastBuffer.getBigUint64(0, littleEndian)
178
+ const hi = idLastBuffer.getBigUint64(8, littleEndian)
179
+ return (hi << 64n) | lo
180
+ }
package/src/node.zig CHANGED
@@ -15,8 +15,9 @@ const Transfer = tb.Transfer;
15
15
  const TransferFlags = tb.TransferFlags;
16
16
  const CreateAccountsResult = tb.CreateAccountsResult;
17
17
  const CreateTransfersResult = tb.CreateTransfersResult;
18
- const GetAccountTransfers = tb.GetAccountTransfers;
19
- const GetAccountTransfersFlags = tb.GetAccountTransfersFlags;
18
+ const AccountFilter = tb.AccountFilter;
19
+ const AccountFilterFlags = tb.AccountFilterFlags;
20
+ const AccountBalance = tb.AccountBalance;
20
21
 
21
22
  const Storage = @import("../../../storage.zig").Storage;
22
23
  const StateMachine = @import("../../../state_machine.zig").StateMachineType(Storage, constants.state_machine_config);
@@ -367,7 +368,7 @@ fn decode_array(comptime Event: type, env: c.napi_env, array: c.napi_value, even
367
368
  for (events, 0..) |*event, i| {
368
369
  const object = try translate.array_element(env, array, @intCast(i));
369
370
  switch (Event) {
370
- Account, Transfer, GetAccountTransfers => {
371
+ Account, Transfer, AccountFilter, AccountBalance => {
371
372
  inline for (std.meta.fields(Event)) |field| {
372
373
  const value: field.type = switch (@typeInfo(field.type)) {
373
374
  .Struct => |info| @bitCast(try @field(
@@ -419,6 +420,8 @@ fn encode_array(comptime Result: type, env: c.napi_env, results: []const Result)
419
420
  const FieldInt = switch (@typeInfo(field.type)) {
420
421
  .Struct => |info| info.backing_integer.?,
421
422
  .Enum => |info| info.tag_type,
423
+ // Arrays are only used for padding/reserved fields.
424
+ .Array => continue,
422
425
  else => field.type,
423
426
  };
424
427
 
@@ -474,9 +477,7 @@ fn BufferType(comptime op: Operation) type {
474
477
  // Allocate enough bytes to hold memory for the Events and the Results.
475
478
  const max_bytes = @max(
476
479
  @sizeOf(Event) * count,
477
- @sizeOf(Result) *
478
- // Ad-hoc hack, event and result sizes are not the same size.
479
- if (op == .get_account_transfers) 8190 else count,
480
+ @sizeOf(Result) * event_count(op, count),
480
481
  );
481
482
  if (@sizeOf(vsr.Header) + max_bytes > constants.message_size_max) {
482
483
  return translate.throw(env, "Batch is larger than the maximum message size.");
@@ -496,9 +497,7 @@ fn BufferType(comptime op: Operation) type {
496
497
  fn free(buffer: Buffer) void {
497
498
  const max_bytes = @max(
498
499
  @sizeOf(Event) * buffer.count,
499
- @sizeOf(Result) *
500
- //TODO(batiati): Refine the way we handle events with asymmetric results.
501
- if (op == .get_account_transfers) 8190 else buffer.count,
500
+ @sizeOf(Result) * event_count(op, buffer.count),
502
501
  );
503
502
  const bytes: []align(max_align) u8 = @alignCast(buffer.ptr[0..max_bytes]);
504
503
  allocator.free(bytes);
@@ -510,10 +509,16 @@ fn BufferType(comptime op: Operation) type {
510
509
  }
511
510
 
512
511
  fn results(buffer: Buffer) []Result {
513
- const result_bytes = buffer.ptr[0 .. @sizeOf(Result) *
514
- // Ad-hoc hack, event and result sizes are not the same size.
515
- if (op == .get_account_transfers) 8190 else buffer.count];
512
+ const result_bytes = buffer.ptr[0 .. @sizeOf(Result) * event_count(op, buffer.count)];
516
513
  return @alignCast(std.mem.bytesAsSlice(Result, result_bytes));
517
514
  }
515
+
516
+ fn event_count(operation: Operation, count: usize) usize {
517
+ // TODO(batiati): Refine the way we handle events with asymmetric results.
518
+ return switch (operation) {
519
+ .get_account_transfers, .get_account_history => 8190,
520
+ else => count,
521
+ };
522
+ }
518
523
  };
519
524
  }