Skip to content

Commit

Permalink
Ledger: add APIs for getting allocation and distribution by ID
Browse files Browse the repository at this point in the history
  • Loading branch information
blueridger committed Nov 24, 2020
1 parent f16c898 commit 86ffba4
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
53 changes: 51 additions & 2 deletions src/core/ledger/ledger.js
Expand Up @@ -25,10 +25,12 @@ import {type NodeAddressT, NodeAddress} from "../graph";
import {type TimestampMs} from "../../util/timestamp";
import * as NullUtil from "../../util/null";
import * as uuid from "../../util/uuid";
import {type Uuid as UuidT} from "../../util/uuid";
import {type Distribution, parser as distributionParser} from "./distribution";
import * as G from "./grain";
import {JsonLog} from "../../util/jsonLog";
import * as C from "../../util/combo";
import {type Allocation} from "./grainAllocation";

/**
* Every Identity in the ledger has an Account.
Expand Down Expand Up @@ -80,6 +82,8 @@ export class Ledger {
_lowercaseNames: Set<string>;
_aliasAddressToIdentity: Map<NodeAddressT, IdentityId>;
_accounts: Map<IdentityId, MutableAccount>;
_allocations: Map<UuidT, Allocation>;
_distributions: Map<UuidT, Distribution>;
_latestTimestamp: TimestampMs = -Infinity;
_lastDistributionTimestamp: TimestampMs = -Infinity;

Expand All @@ -89,6 +93,8 @@ export class Ledger {
this._lowercaseNames = new Set();
this._aliasAddressToIdentity = new Map();
this._accounts = new Map();
this._allocations = new Map();
this._distributions = new Map();
}

/**
Expand Down Expand Up @@ -159,6 +165,47 @@ export class Ledger {
return this.account(identityId);
}

/**
* Get the Allocation associated with a particular Allocation ID.
*
* If the ID is not in the ledger, an error is thrown.
*/
allocation(id: UuidT): Allocation {
const allocation = this._allocations.get(id);
if (allocation == null) throw new Error(`no Allocation for id: ${id}`);
return allocation;
}

/**
* Get the Distribution associated with a particular Distribution ID.
*
* If the ID is not in the ledger, an error is thrown.
*/
distribution(id: UuidT): Distribution {
const distribution = this._distributions.get(id);
if (distribution == null) throw new Error(`no Distribution for id: ${id}`);
return distribution;
}

/**
* Get the Distribution associated with a particular Allocation ID.
*
* If the Allocation ID is not associated with a distribution, an error is thrown.
*
* This is less efficient than the `distribution` method.
*/
distributionByAllocationId(allocationId: UuidT): Distribution {
for (const distribution of this._distributions.values()) {
if (
distribution.allocations.find(
(allocation) => allocation.id === allocationId
)
)
return distribution;
}
throw new Error(`no Distribution for allocation id: ${allocationId}`);
}

/**
* Create an account in the ledger.
*
Expand Down Expand Up @@ -467,8 +514,10 @@ export class Ledger {
}
}
// Mutations beckon: method must not fail after this comment
for (const {receipts} of distribution.allocations) {
for (const {id, amount} of receipts) {
this._distributions.set(distribution.id, distribution);
for (const allocation of distribution.allocations) {
this._allocations.set(allocation.id, allocation);
for (const {id, amount} of allocation.receipts) {
this._allocateGrain(id, amount);
}
}
Expand Down
34 changes: 34 additions & 0 deletions src/core/ledger/ledger.test.js
Expand Up @@ -823,6 +823,11 @@ describe("core/ledger/ledger", () => {
active: true,
};
expect(ledger.accounts()).toEqual([ac1, ac2]);
expect(ledger.allocation(allocation.id)).toEqual(allocation);
expect(ledger.distribution(distribution.id)).toEqual(distribution);
expect(ledger.distributionByAllocationId(allocation.id)).toEqual(
distribution
);
});
it("handles multiple allocations", () => {
const ledger = ledgerWithActiveIdentities();
Expand Down Expand Up @@ -861,6 +866,15 @@ describe("core/ledger/ledger", () => {
active: true,
};
expect(ledger.accounts()).toEqual([ac1, ac2]);
expect(ledger.allocation(allocation1.id)).toEqual(allocation1);
expect(ledger.allocation(allocation2.id)).toEqual(allocation2);
expect(ledger.distribution(distribution.id)).toEqual(distribution);
expect(ledger.distributionByAllocationId(allocation1.id)).toEqual(
distribution
);
expect(ledger.distributionByAllocationId(allocation2.id)).toEqual(
distribution
);
});
it("fails if any receipt has invalid id", () => {
const ledger = ledgerWithActiveIdentities();
Expand Down Expand Up @@ -1098,6 +1112,26 @@ describe("core/ledger/ledger", () => {
});
});

describe("distribution and allocation lookups", () => {
it("allocation throws when an invalid ID is provided", () => {
const ledger = new Ledger();
const thunk = () => ledger.allocation(uuid.random());
expect(thunk).toThrowError("no Allocation for id");
});

it("distribution throws when an invalid ID is provided", () => {
const ledger = new Ledger();
const thunk = () => ledger.distribution(uuid.random());
expect(thunk).toThrowError("no Distribution for id");
});

it("distributionByAllocationId throws when an invalid ID is provided", () => {
const ledger = new Ledger();
const thunk = () => ledger.distributionByAllocationId(uuid.random());
expect(thunk).toThrowError("no Distribution for allocation id");
});
});

describe("timestamps", () => {
it("out-of-order events are illegal", () => {
const ledger = new Ledger();
Expand Down

0 comments on commit 86ffba4

Please sign in to comment.