tigerbeetle-node
Advanced tools
Comparing version 0.14.178 to 0.14.179
@@ -5,3 +5,4 @@ export declare enum AccountFlags { | ||
debits_must_not_exceed_credits = 2, | ||
credits_must_not_exceed_debits = 4 | ||
credits_must_not_exceed_debits = 4, | ||
history = 8 | ||
} | ||
@@ -17,3 +18,3 @@ export declare enum TransferFlags { | ||
} | ||
export declare enum GetAccountTransfersFlags { | ||
export declare enum AccountFilterFlags { | ||
none = 0, | ||
@@ -144,3 +145,3 @@ debits = 1, | ||
}; | ||
export declare type GetAccountTransfers = { | ||
export declare type AccountFilter = { | ||
account_id: bigint; | ||
@@ -152,2 +153,9 @@ timestamp_min: bigint; | ||
}; | ||
export declare type AccountBalance = { | ||
debits_pending: bigint; | ||
debits_posted: bigint; | ||
credits_pending: bigint; | ||
credits_posted: bigint; | ||
timestamp: bigint; | ||
}; | ||
export declare enum Operation { | ||
@@ -158,3 +166,4 @@ create_accounts = 128, | ||
lookup_transfers = 131, | ||
get_account_transfers = 132 | ||
get_account_transfers = 132, | ||
get_account_history = 133 | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Operation = exports.CreateTransferError = exports.CreateAccountError = exports.GetAccountTransfersFlags = exports.TransferFlags = exports.AccountFlags = void 0; | ||
exports.Operation = exports.CreateTransferError = exports.CreateAccountError = exports.AccountFilterFlags = exports.TransferFlags = exports.AccountFlags = void 0; | ||
var AccountFlags; | ||
@@ -10,2 +10,3 @@ (function (AccountFlags) { | ||
AccountFlags[AccountFlags["credits_must_not_exceed_debits"] = 4] = "credits_must_not_exceed_debits"; | ||
AccountFlags[AccountFlags["history"] = 8] = "history"; | ||
})(AccountFlags = exports.AccountFlags || (exports.AccountFlags = {})); | ||
@@ -22,9 +23,9 @@ var TransferFlags; | ||
})(TransferFlags = exports.TransferFlags || (exports.TransferFlags = {})); | ||
var GetAccountTransfersFlags; | ||
(function (GetAccountTransfersFlags) { | ||
GetAccountTransfersFlags[GetAccountTransfersFlags["none"] = 0] = "none"; | ||
GetAccountTransfersFlags[GetAccountTransfersFlags["debits"] = 1] = "debits"; | ||
GetAccountTransfersFlags[GetAccountTransfersFlags["credits"] = 2] = "credits"; | ||
GetAccountTransfersFlags[GetAccountTransfersFlags["reversed"] = 4] = "reversed"; | ||
})(GetAccountTransfersFlags = exports.GetAccountTransfersFlags || (exports.GetAccountTransfersFlags = {})); | ||
var AccountFilterFlags; | ||
(function (AccountFilterFlags) { | ||
AccountFilterFlags[AccountFilterFlags["none"] = 0] = "none"; | ||
AccountFilterFlags[AccountFilterFlags["debits"] = 1] = "debits"; | ||
AccountFilterFlags[AccountFilterFlags["credits"] = 2] = "credits"; | ||
AccountFilterFlags[AccountFilterFlags["reversed"] = 4] = "reversed"; | ||
})(AccountFilterFlags = exports.AccountFilterFlags || (exports.AccountFilterFlags = {})); | ||
var CreateAccountError; | ||
@@ -121,3 +122,4 @@ (function (CreateAccountError) { | ||
Operation[Operation["get_account_transfers"] = 132] = "get_account_transfers"; | ||
Operation[Operation["get_account_history"] = 133] = "get_account_history"; | ||
})(Operation = exports.Operation || (exports.Operation = {})); | ||
//# sourceMappingURL=bindings.js.map |
export * from './bindings'; | ||
import { Account, Transfer, CreateAccountsError, CreateTransfersError, GetAccountTransfers } from './bindings'; | ||
import { Account, Transfer, CreateAccountsError, CreateTransfersError, AccountFilter, AccountBalance } from './bindings'; | ||
export declare type Context = object; | ||
export declare type AccountID = bigint; | ||
export declare type TransferID = bigint; | ||
export declare type Event = Account | Transfer | AccountID | TransferID | GetAccountTransfers; | ||
export declare type Result = CreateAccountsError | CreateTransfersError | Account | Transfer; | ||
export declare type Event = Account | Transfer | AccountID | TransferID | AccountFilter; | ||
export declare type Result = CreateAccountsError | CreateTransfersError | Account | Transfer | AccountBalance; | ||
export declare type ResultCallback = (error: Error | null, results: Result[] | null) => void; | ||
@@ -19,5 +19,7 @@ export interface ClientInitArgs { | ||
lookupTransfers: (batch: TransferID[]) => Promise<Transfer[]>; | ||
getAccountTransfers: (filter: GetAccountTransfers) => Promise<Transfer[]>; | ||
getAccountTransfers: (filter: AccountFilter) => Promise<Transfer[]>; | ||
getAccountHistory: (filter: AccountFilter) => Promise<AccountBalance[]>; | ||
destroy: () => void; | ||
} | ||
export declare function createClient(args: ClientInitArgs): Client; | ||
export declare function id(): bigint; |
@@ -13,5 +13,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createClient = void 0; | ||
exports.id = exports.createClient = void 0; | ||
__exportStar(require("./bindings"), exports); | ||
const bindings_1 = require("./bindings"); | ||
const node_crypto_1 = require("node:crypto"); | ||
const binding = (() => { | ||
@@ -83,2 +84,3 @@ const { arch, platform } = process; | ||
getAccountTransfers(filter) { return request(bindings_1.Operation.get_account_transfers, [filter]); }, | ||
getAccountHistory(filter) { return request(bindings_1.Operation.get_account_history, [filter]); }, | ||
destroy() { binding.deinit(context); }, | ||
@@ -88,2 +90,30 @@ }; | ||
exports.createClient = createClient; | ||
let idLastTimestamp = 0; | ||
let idLastBuffer = new DataView(new ArrayBuffer(16)); | ||
function id() { | ||
let timestamp = Date.now(); | ||
if (timestamp <= idLastTimestamp) { | ||
timestamp = idLastTimestamp; | ||
} | ||
else { | ||
idLastTimestamp = timestamp; | ||
(0, node_crypto_1.randomFillSync)(idLastBuffer); | ||
} | ||
const littleEndian = true; | ||
const randomLo32 = idLastBuffer.getUint32(0, littleEndian) + 1; | ||
const randomHi32 = idLastBuffer.getUint32(4, littleEndian) + (randomLo32 > 0xFFFFFFFF ? 1 : 0); | ||
const randomHi16 = idLastBuffer.getUint16(8, littleEndian) + (randomHi32 > 0xFFFFFFFF ? 1 : 0); | ||
if (randomHi16 > 0xFFFF) { | ||
throw new Error('random bits overflow on monotonic increment'); | ||
} | ||
idLastBuffer.setUint32(0, randomLo32 & 0xFFFFFFFF, littleEndian); | ||
idLastBuffer.setUint32(4, randomHi32 & 0xFFFFFFFF, littleEndian); | ||
idLastBuffer.setUint16(8, randomHi16, littleEndian); | ||
idLastBuffer.setUint16(10, timestamp & 0xFFFF, littleEndian); | ||
idLastBuffer.setUint32(12, (timestamp >>> 16) & 0xFFFFFFFF, littleEndian); | ||
const lo = idLastBuffer.getBigUint64(0, littleEndian); | ||
const hi = idLastBuffer.getBigUint64(8, littleEndian); | ||
return (hi << 64n) | lo; | ||
} | ||
exports.id = id; | ||
//# sourceMappingURL=index.js.map |
124
dist/test.js
@@ -51,2 +51,13 @@ "use strict"; | ||
}; | ||
test('id() monotonically increasing', async () => { | ||
let idA = (0, _1.id)(); | ||
for (let i = 0; i < 10000000; i++) { | ||
if (i % 10000 == 0) { | ||
await new Promise(resolve => setTimeout(resolve, 1)); | ||
} | ||
const idB = (0, _1.id)(); | ||
assert_1.default.ok(idB > idA, 'id() returned an id that did not monotonically increase'); | ||
idA = idB; | ||
} | ||
}); | ||
test('range check `code` on Account to be u16', async () => { | ||
@@ -352,3 +363,3 @@ const account = { ...accountA, id: 0n }; | ||
code: 718, | ||
flags: 0, | ||
flags: _1.AccountFlags.history, | ||
timestamp: 0n | ||
@@ -383,10 +394,15 @@ }; | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
var transfers = await client.getAccountTransfers(filter); | ||
var history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, transfers_created.length); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
var timestamp = 0n; | ||
var i = 0; | ||
for (var transfer of transfers) { | ||
assert_1.default.ok(timestamp < transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert_1.default.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -398,10 +414,15 @@ filter = { | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.debits | _1.GetAccountTransfersFlags.reversed, | ||
flags: _1.AccountFilterFlags.debits | _1.AccountFilterFlags.reversed, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, transfers_created.length / 2); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
timestamp = 1n << 64n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert_1.default.ok(transfer.timestamp < timestamp); | ||
timestamp = transfer.timestamp; | ||
assert_1.default.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -413,10 +434,15 @@ filter = { | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.reversed, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.reversed, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, transfers_created.length / 2); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
timestamp = 1n << 64n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert_1.default.ok(transfer.timestamp < timestamp); | ||
timestamp = transfer.timestamp; | ||
assert_1.default.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -428,10 +454,15 @@ filter = { | ||
limit: transfers_created.length / 2, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, transfers_created.length / 2); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
timestamp = 0n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert_1.default.ok(timestamp < transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert_1.default.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -443,9 +474,14 @@ filter = { | ||
limit: transfers_created.length / 2, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, transfers_created.length / 2); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert_1.default.ok(timestamp < transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert_1.default.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -457,6 +493,8 @@ filter = { | ||
limit: transfers_created.length / 2, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, 0); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
filter = { | ||
@@ -467,10 +505,15 @@ account_id: accountC.id, | ||
limit: transfers_created.length / 2, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits | _1.GetAccountTransfersFlags.reversed, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits | _1.AccountFilterFlags.reversed, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, transfers_created.length / 2); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
timestamp = 1n << 64n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert_1.default.ok(timestamp > transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert_1.default.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -482,9 +525,14 @@ filter = { | ||
limit: transfers_created.length / 2, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits | _1.GetAccountTransfersFlags.reversed, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits | _1.AccountFilterFlags.reversed, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, transfers_created.length / 2); | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert_1.default.ok(timestamp > transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert_1.default.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -496,7 +544,9 @@ filter = { | ||
limit: transfers_created.length / 2, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits | _1.GetAccountTransfersFlags.reversed, | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits | _1.AccountFilterFlags.reversed, | ||
}; | ||
transfers = await client.getAccountTransfers(filter); | ||
history = await client.getAccountHistory(filter); | ||
assert_1.default.strictEqual(transfers.length, 0); | ||
assert_1.default.strictEqual((await client.getAccountTransfers({ | ||
assert_1.default.strictEqual(history.length, transfers.length); | ||
filter = { | ||
account_id: 0n, | ||
@@ -506,5 +556,7 @@ timestamp_min: 0n, | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
})).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountTransfers({ | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
assert_1.default.strictEqual((await client.getAccountTransfers(filter)).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountHistory(filter)).length, 0); | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -514,5 +566,7 @@ timestamp_min: (1n << 64n) - 1n, | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
})).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountTransfers({ | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
assert_1.default.strictEqual((await client.getAccountTransfers(filter)).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountHistory(filter)).length, 0); | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -522,5 +576,7 @@ timestamp_min: 0n, | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
})).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountTransfers({ | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
assert_1.default.strictEqual((await client.getAccountTransfers(filter)).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountHistory(filter)).length, 0); | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -530,5 +586,7 @@ timestamp_min: (1n << 64n) - 2n, | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
})).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountTransfers({ | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
assert_1.default.strictEqual((await client.getAccountTransfers(filter)).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountHistory(filter)).length, 0); | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -538,5 +596,7 @@ timestamp_min: 0n, | ||
limit: 0, | ||
flags: _1.GetAccountTransfersFlags.credits | _1.GetAccountTransfersFlags.debits, | ||
})).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountTransfers({ | ||
flags: _1.AccountFilterFlags.credits | _1.AccountFilterFlags.debits, | ||
}; | ||
assert_1.default.strictEqual((await client.getAccountTransfers(filter)).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountHistory(filter)).length, 0); | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -546,5 +606,7 @@ timestamp_min: 0n, | ||
limit: 8190, | ||
flags: _1.GetAccountTransfersFlags.none, | ||
})).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountTransfers({ | ||
flags: _1.AccountFilterFlags.none, | ||
}; | ||
assert_1.default.strictEqual((await client.getAccountTransfers(filter)).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountHistory(filter)).length, 0); | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -555,3 +617,5 @@ timestamp_min: 0n, | ||
flags: 0xFFFF, | ||
})).length, 0); | ||
}; | ||
assert_1.default.strictEqual((await client.getAccountTransfers(filter)).length, 0); | ||
assert_1.default.strictEqual((await client.getAccountHistory(filter)).length, 0); | ||
}); | ||
@@ -558,0 +622,0 @@ async function main() { |
{ | ||
"name": "tigerbeetle-node", | ||
"version": "0.14.178", | ||
"version": "0.14.179", | ||
"description": "TigerBeetle Node.js client", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -129,2 +129,3 @@ --- | ||
* `AccountFlags.credits_must_not_exceed_credits` | ||
* `AccountFlags.history` | ||
@@ -580,6 +581,6 @@ | ||
timestamp_max: 0n, // No filter by Timestamp. | ||
limit: 10, // Limit to ten transfers at most. | ||
flags: GetAccountTransfersFlags.debits | // Include transfer from the debit side. | ||
GetAccountTransfersFlags.credits | // Include transfer from the credit side. | ||
GetAccountTransfersFlags.reversed, // Sort by timestamp in reverse-chronological order. | ||
limit: 10, // Limit to ten balances at most. | ||
flags: AccountFilterFlags.debits | // Include transfer from the debit side. | ||
AccountFilterFlags.credits | // Include transfer from the credit side. | ||
AccountFilterFlags.reversed, // Sort by timestamp in reverse-chronological order. | ||
}; | ||
@@ -589,2 +590,30 @@ const account_transfers = await client.getAccountTransfers(filter); | ||
## Get Account History | ||
NOTE: This is a preview API that is subject to breaking changes once we have | ||
a stable querying API. | ||
Fetches the point-in-time balances of a given account, allowing basic filter and | ||
pagination capabilities. | ||
Only accounts created with the flag | ||
[`history`](https://docs.tigerbeetle.com/reference/accounts#flagshistory) set retain | ||
the history of balances. | ||
The balances in the response are sorted by `timestamp` in chronological or | ||
reverse-chronological order. | ||
```javascript | ||
filter = { | ||
account_id: 2n, | ||
timestamp_min: 0n, // No filter by Timestamp. | ||
timestamp_max: 0n, // No filter by Timestamp. | ||
limit: 10, // Limit to ten balances at most. | ||
flags: AccountFilterFlags.debits | // Include transfer from the debit side. | ||
AccountFilterFlags.credits | // Include transfer from the credit side. | ||
AccountFilterFlags.reversed, // Sort by timestamp in reverse-chronological order. | ||
}; | ||
const account_balances = await client.getAccountHistory(filter); | ||
``` | ||
## Linked Events | ||
@@ -591,0 +620,0 @@ |
@@ -27,2 +27,7 @@ /////////////////////////////////////////////////////// | ||
credits_must_not_exceed_debits = (1 << 2), | ||
/** | ||
* See [history](https://docs.tigerbeetle.com/reference/accounts#flagshistory) | ||
*/ | ||
history = (1 << 3), | ||
} | ||
@@ -70,9 +75,9 @@ | ||
/** | ||
* See [GetAccountTransfersFlags](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flags) | ||
* See [AccountFilterFlags](https://docs.tigerbeetle.com/reference/account_filter#flags) | ||
*/ | ||
export enum GetAccountTransfersFlags { | ||
export enum AccountFilterFlags { | ||
none = 0, | ||
/** | ||
* See [debits](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flagsdebits) | ||
* See [debits](https://docs.tigerbeetle.com/reference/account_filter#flagsdebits) | ||
*/ | ||
@@ -82,3 +87,3 @@ debits = (1 << 0), | ||
/** | ||
* See [credits](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flagscredits) | ||
* See [credits](https://docs.tigerbeetle.com/reference/account_filter#flagscredits) | ||
*/ | ||
@@ -88,3 +93,3 @@ credits = (1 << 1), | ||
/** | ||
* See [reversed](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flagsreversed) | ||
* See [reversed](https://docs.tigerbeetle.com/reference/account_filter#flagsreversed) | ||
*/ | ||
@@ -654,8 +659,8 @@ reversed = (1 << 2), | ||
/** | ||
* See [GetAccountTransfers](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#) | ||
* See [AccountFilter](https://docs.tigerbeetle.com/reference/account_filter#) | ||
*/ | ||
export type GetAccountTransfers = { | ||
export type AccountFilter = { | ||
/** | ||
* See [account_id](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#account_id) | ||
* See [account_id](https://docs.tigerbeetle.com/reference/account_filter#account_id) | ||
*/ | ||
@@ -665,3 +670,3 @@ account_id: bigint | ||
/** | ||
* See [timestamp_min](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#timestamp_min) | ||
* See [timestamp_min](https://docs.tigerbeetle.com/reference/account_filter#timestamp_min) | ||
*/ | ||
@@ -671,3 +676,3 @@ timestamp_min: bigint | ||
/** | ||
* See [timestamp_max](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#timestamp_max) | ||
* See [timestamp_max](https://docs.tigerbeetle.com/reference/account_filter#timestamp_max) | ||
*/ | ||
@@ -677,3 +682,3 @@ timestamp_max: bigint | ||
/** | ||
* See [limit](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#limit) | ||
* See [limit](https://docs.tigerbeetle.com/reference/account_filter#limit) | ||
*/ | ||
@@ -683,3 +688,3 @@ limit: number | ||
/** | ||
* See [flags](https://docs.tigerbeetle.com/reference/operations/get_account_transfers#flags) | ||
* See [flags](https://docs.tigerbeetle.com/reference/account_filter#flags) | ||
*/ | ||
@@ -689,2 +694,34 @@ flags: number | ||
/** | ||
* See [AccountBalance](https://docs.tigerbeetle.com/reference/account_balances#) | ||
*/ | ||
export type AccountBalance = { | ||
/** | ||
* See [debits_pending](https://docs.tigerbeetle.com/reference/account_balances#debits_pending) | ||
*/ | ||
debits_pending: bigint | ||
/** | ||
* See [debits_posted](https://docs.tigerbeetle.com/reference/account_balances#debits_posted) | ||
*/ | ||
debits_posted: bigint | ||
/** | ||
* See [credits_pending](https://docs.tigerbeetle.com/reference/account_balances#credits_pending) | ||
*/ | ||
credits_pending: bigint | ||
/** | ||
* See [credits_posted](https://docs.tigerbeetle.com/reference/account_balances#credits_posted) | ||
*/ | ||
credits_posted: bigint | ||
/** | ||
* See [timestamp](https://docs.tigerbeetle.com/reference/account_balances#timestamp) | ||
*/ | ||
timestamp: bigint | ||
} | ||
export enum Operation { | ||
@@ -696,3 +733,4 @@ create_accounts = 128, | ||
get_account_transfers = 132, | ||
get_account_history = 133, | ||
} | ||
@@ -8,4 +8,6 @@ export * from './bindings' | ||
Operation, | ||
GetAccountTransfers, | ||
AccountFilter, | ||
AccountBalance, | ||
} from './bindings' | ||
import { randomFillSync } from 'node:crypto' | ||
@@ -70,4 +72,4 @@ const binding: Binding = (() => { | ||
export type TransferID = bigint // u128 | ||
export type Event = Account | Transfer | AccountID | TransferID | GetAccountTransfers | ||
export type Result = CreateAccountsError | CreateTransfersError | Account | Transfer | ||
export type Event = Account | Transfer | AccountID | TransferID | AccountFilter | ||
export type Result = CreateAccountsError | CreateTransfersError | Account | Transfer | AccountBalance | ||
export type ResultCallback = (error: Error | null, results: Result[] | null) => void | ||
@@ -98,3 +100,4 @@ | ||
lookupTransfers: (batch: TransferID[]) => Promise<Transfer[]> | ||
getAccountTransfers: (filter: GetAccountTransfers) => Promise<Transfer[]> | ||
getAccountTransfers: (filter: AccountFilter) => Promise<Transfer[]> | ||
getAccountHistory: (filter: AccountFilter) => Promise<AccountBalance[]> | ||
destroy: () => void | ||
@@ -135,4 +138,47 @@ } | ||
getAccountTransfers(filter) { return request(Operation.get_account_transfers, [filter]) }, | ||
getAccountHistory(filter) { return request(Operation.get_account_history, [filter]) }, | ||
destroy() { binding.deinit(context) }, | ||
} | ||
} | ||
let idLastTimestamp = 0; | ||
let idLastBuffer = new DataView(new ArrayBuffer(16)); | ||
/** | ||
* Generates a Universally Unique and Sortable Identifier as a u128 bigint. | ||
* | ||
* @remarks | ||
* Based on {@link https://github.com/ulid/spec}, IDs returned are guaranteed to be monotonically | ||
* increasing. | ||
*/ | ||
export function id(): bigint { | ||
// Ensure timestamp monotonically increases and generate a new random on each new timestamp. | ||
let timestamp = Date.now() | ||
if (timestamp <= idLastTimestamp) { | ||
timestamp = idLastTimestamp | ||
} else { | ||
idLastTimestamp = timestamp | ||
randomFillSync(idLastBuffer) | ||
} | ||
// Increment the u80 in idLastBuffer using carry arithmetic on u32s (as JS doesn't have fast u64). | ||
const littleEndian = true | ||
const randomLo32 = idLastBuffer.getUint32(0, littleEndian) + 1 | ||
const randomHi32 = idLastBuffer.getUint32(4, littleEndian) + (randomLo32 > 0xFFFFFFFF ? 1 : 0) | ||
const randomHi16 = idLastBuffer.getUint16(8, littleEndian) + (randomHi32 > 0xFFFFFFFF ? 1 : 0) | ||
if (randomHi16 > 0xFFFF) { | ||
throw new Error('random bits overflow on monotonic increment') | ||
} | ||
// Store the incremented random monotonic and the timestamp into the buffer. | ||
idLastBuffer.setUint32(0, randomLo32 & 0xFFFFFFFF, littleEndian) | ||
idLastBuffer.setUint32(4, randomHi32 & 0xFFFFFFFF, littleEndian) | ||
idLastBuffer.setUint16(8, randomHi16, littleEndian) // No need to mask since checked above. | ||
idLastBuffer.setUint16(10, timestamp & 0xFFFF, littleEndian) // timestamp lo. | ||
idLastBuffer.setUint32(12, (timestamp >>> 16) & 0xFFFFFFFF, littleEndian) // timestamp hi. | ||
// Then return the buffer's contents as a little-endian u128 bigint. | ||
const lo = idLastBuffer.getBigUint64(0, littleEndian) | ||
const hi = idLastBuffer.getBigUint64(8, littleEndian) | ||
return (hi << 64n) | lo | ||
} |
159
src/test.ts
@@ -9,4 +9,6 @@ import assert, { AssertionError } from 'assert' | ||
CreateTransferError, | ||
GetAccountTransfers, | ||
GetAccountTransfersFlags, | ||
AccountFilter, | ||
AccountFilterFlags, | ||
AccountFlags, | ||
id, | ||
} from '.' | ||
@@ -61,2 +63,16 @@ | ||
test('id() monotonically increasing', async (): Promise<void> => { | ||
let idA = id(); | ||
for (let i = 0; i < 10_000_000; i++) { | ||
// Ensure ID is monotonic between milliseconds if the loop executes too fast. | ||
if (i % 10_000 == 0) { | ||
await new Promise(resolve => setTimeout(resolve, 1)) | ||
} | ||
const idB = id(); | ||
assert.ok(idB > idA, 'id() returned an id that did not monotonically increase'); | ||
idA = idB; | ||
} | ||
}) | ||
test('range check `code` on Account to be u16', async (): Promise<void> => { | ||
@@ -409,3 +425,3 @@ const account = { ...accountA, id: 0n } | ||
code: 718, | ||
flags: 0, | ||
flags: AccountFlags.history, | ||
timestamp: 0n | ||
@@ -440,3 +456,3 @@ } | ||
// Query all transfers for accountC: | ||
var filter: GetAccountTransfers = { | ||
var filter: AccountFilter = { | ||
account_id: accountC.id, | ||
@@ -446,10 +462,17 @@ timestamp_min: 0n, | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
var transfers = await client.getAccountTransfers(filter) | ||
var history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, transfers_created.length) | ||
assert.strictEqual(history.length, transfers.length) | ||
var timestamp = 0n; | ||
var i = 0; | ||
for (var transfer of transfers) { | ||
assert.ok(timestamp < transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -463,10 +486,18 @@ | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.debits | GetAccountTransfersFlags.reversed, | ||
flags: AccountFilterFlags.debits | AccountFilterFlags.reversed, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, transfers_created.length / 2) | ||
assert.strictEqual(history.length, transfers.length) | ||
timestamp = 1n << 64n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert.ok(transfer.timestamp < timestamp); | ||
timestamp = transfer.timestamp; | ||
assert.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -480,10 +511,18 @@ | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.reversed, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.reversed, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, transfers_created.length / 2) | ||
assert.strictEqual(history.length, transfers.length) | ||
timestamp = 1n << 64n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert.ok(transfer.timestamp < timestamp); | ||
timestamp = transfer.timestamp; | ||
assert.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -497,10 +536,18 @@ | ||
limit: transfers_created.length / 2, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, transfers_created.length / 2) | ||
assert.strictEqual(history.length, transfers.length) | ||
timestamp = 0n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert.ok(timestamp < transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -514,9 +561,17 @@ | ||
limit: transfers_created.length / 2, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, transfers_created.length / 2) | ||
assert.strictEqual(history.length, transfers.length) | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert.ok(timestamp < transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -530,6 +585,9 @@ | ||
limit: transfers_created.length / 2, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, 0) | ||
assert.strictEqual(history.length, transfers.length) | ||
@@ -542,10 +600,18 @@ // Query the first 5 transfers for accountC ORDER BY DESC: | ||
limit: transfers_created.length / 2, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits | GetAccountTransfersFlags.reversed, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits | AccountFilterFlags.reversed, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, transfers_created.length / 2) | ||
assert.strictEqual(history.length, transfers.length) | ||
timestamp = 1n << 64n; | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert.ok(timestamp > transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -559,9 +625,17 @@ | ||
limit: transfers_created.length / 2, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits | GetAccountTransfersFlags.reversed, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits | AccountFilterFlags.reversed, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, transfers_created.length / 2) | ||
assert.strictEqual(history.length, transfers.length) | ||
i = 0; | ||
for (var transfer of transfers) { | ||
assert.ok(timestamp > transfer.timestamp); | ||
timestamp = transfer.timestamp; | ||
assert.ok(history[i].timestamp == transfer.timestamp); | ||
i++; | ||
} | ||
@@ -575,9 +649,12 @@ | ||
limit: transfers_created.length / 2, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits | GetAccountTransfersFlags.reversed, | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits | AccountFilterFlags.reversed, | ||
} | ||
transfers = await client.getAccountTransfers(filter) | ||
assert.strictEqual(transfers.length, 0) | ||
history = await client.getAccountHistory(filter) | ||
assert.strictEqual(transfers.length, 0) | ||
assert.strictEqual(history.length, transfers.length) | ||
// Invalid account: | ||
assert.strictEqual((await client.getAccountTransfers({ | ||
filter = { | ||
account_id: 0n, | ||
@@ -587,7 +664,9 @@ timestamp_min: 0n, | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
})).length, 0) | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
assert.strictEqual((await client.getAccountTransfers(filter)).length, 0) | ||
assert.strictEqual((await client.getAccountHistory(filter)).length, 0) | ||
// Invalid timestamp min: | ||
assert.strictEqual((await client.getAccountTransfers({ | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -597,7 +676,9 @@ timestamp_min: (1n << 64n) - 1n, // ulong max value | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
})).length, 0) | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
assert.strictEqual((await client.getAccountTransfers(filter)).length, 0) | ||
assert.strictEqual((await client.getAccountHistory(filter)).length, 0) | ||
// Invalid timestamp max: | ||
assert.strictEqual((await client.getAccountTransfers({ | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -607,7 +688,9 @@ timestamp_min: 0n, | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
})).length, 0) | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
assert.strictEqual((await client.getAccountTransfers(filter)).length, 0) | ||
assert.strictEqual((await client.getAccountHistory(filter)).length, 0) | ||
// Invalid timestamp range: | ||
assert.strictEqual((await client.getAccountTransfers({ | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -617,7 +700,9 @@ timestamp_min: (1n << 64n) - 2n, // ulong max - 1 | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
})).length, 0) | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
assert.strictEqual((await client.getAccountTransfers(filter)).length, 0) | ||
assert.strictEqual((await client.getAccountHistory(filter)).length, 0) | ||
// Zero limit: | ||
assert.strictEqual((await client.getAccountTransfers({ | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -627,7 +712,9 @@ timestamp_min: 0n, | ||
limit: 0, | ||
flags: GetAccountTransfersFlags.credits | GetAccountTransfersFlags.debits, | ||
})).length, 0) | ||
flags: AccountFilterFlags.credits | AccountFilterFlags.debits, | ||
} | ||
assert.strictEqual((await client.getAccountTransfers(filter)).length, 0) | ||
assert.strictEqual((await client.getAccountHistory(filter)).length, 0) | ||
// Empty flags: | ||
assert.strictEqual((await client.getAccountTransfers({ | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -637,7 +724,9 @@ timestamp_min: 0n, | ||
limit: 8190, | ||
flags: GetAccountTransfersFlags.none, | ||
})).length, 0) | ||
flags: AccountFilterFlags.none, | ||
} | ||
assert.strictEqual((await client.getAccountTransfers(filter)).length, 0) | ||
assert.strictEqual((await client.getAccountHistory(filter)).length, 0) | ||
// Invalid flags: | ||
assert.strictEqual((await client.getAccountTransfers({ | ||
filter = { | ||
account_id: accountC.id, | ||
@@ -648,3 +737,5 @@ timestamp_min: 0n, | ||
flags: 0xFFFF, | ||
})).length, 0) | ||
} | ||
assert.strictEqual((await client.getAccountTransfers(filter)).length, 0) | ||
assert.strictEqual((await client.getAccountHistory(filter)).length, 0) | ||
@@ -651,0 +742,0 @@ }) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15548551
2757
675