Skip to content

Commit

Permalink
feat(web-stub): implement directory module
Browse files Browse the repository at this point in the history
- add initial accounts on mock
- breaking; add test event
- adjust tests
  • Loading branch information
pandres95 committed Feb 26, 2024
1 parent 4c0d2dd commit e737ed4
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 58 deletions.
2 changes: 1 addition & 1 deletion libs/web-stub/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ticketto/web-stub",
"version": "1.0.6",
"version": "1.1.0",
"description": "A stub-based, web-scoped implementation of The Ticketto Protocol",
"type": "module",
"author": {
Expand Down
69 changes: 69 additions & 0 deletions libs/web-stub/src/directory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Account, AccountId, AccountIdentity } from "@ticketto/types";

import { DirectoryCalls, DirectoryStorage } from "@ticketto/protocol";
import { IDBPDatabase } from "idb";
import { TickettoDBSchema } from "./types.js";
import { inject, injectable } from "inversify";

function boundedByString(s: string): [string, string] {
const inc = (s: string) =>
s === "" ? "" : String.fromCharCode(s.charCodeAt(0) + 1);

const letters = s.split("");
const lastChar = letters.pop();

return [s, letters.concat(inc(lastChar ?? "")).join("")];
}

@injectable()
export class WebStubDirectoryStorage implements DirectoryStorage {
constructor(
@inject("TickettoDB") private db: IDBPDatabase<TickettoDBSchema>
) {}

all(): Promise<Account[]> {
return this.db.getAll("accounts");
}

indexByDisplay(display: string): Promise<Account[]> {
return this.db.getAllFromIndex(
"accounts",
"display",
IDBKeyRange.bound(...boundedByString(display))
);
}

indexByPhone(phone: string): Promise<Account[]> {
return this.db.getAllFromIndex(
"accounts",
"phone",
IDBKeyRange.bound(...boundedByString(phone))
);
}

indexByEmail(email: string): Promise<Account[]> {
return this.db.getAllFromIndex(
"accounts",
"email",
IDBKeyRange.bound(...boundedByString(email))
);
}

get(accountId: AccountId): Promise<Account | undefined> {
return this.db.get("accounts", accountId);
}
}

@injectable()
export class WebStubDirectoryCalls implements DirectoryCalls {
insert(accountId: AccountId, identity: AccountIdentity): Promise<void> {
throw new Error("Method not implemented.");
}

setIdentity(
accountId: AccountId,
identity: Partial<AccountIdentity>
): Promise<void> {
throw new Error("Method not implemented.");
}
}
12 changes: 9 additions & 3 deletions libs/web-stub/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
TickettoClient,
TickettoConsumer,
} from "@ticketto/protocol";
import { WebStubDirectoryCalls, WebStubDirectoryStorage } from "./directory.js";
import { WebStubEventsCalls, WebStubEventsStorage } from "./events.js";
import { WebStubTicketsCalls, WebStubTicketsStorage } from "./tickets.js";

Expand All @@ -14,12 +15,17 @@ import { injectable } from "inversify";
export class TickettoWebStubConsumer implements TickettoConsumer {
constructor(private stub: Stub = new Stub()) {}

async build(config?: ClientConfig): Promise<TickettoClient> {
this.stub.accountProvider = config?.accountProvider;
await this.stub.build(config?.consumerSettings as StubConsumerSettings);
async build(config: ClientConfig): Promise<TickettoClient> {
await this.stub
.withAccountProvider(config.accountProvider)
.build(config.consumerSettings as StubConsumerSettings | undefined);

return {
accountProvider: this.stub.accountProvider!,
directory: {
calls: this.stub.get(WebStubDirectoryCalls),
query: this.stub.get(WebStubDirectoryStorage),
},
events: {
calls: this.stub.get(WebStubEventsCalls),
query: this.stub.get(WebStubEventsStorage),
Expand Down
72 changes: 59 additions & 13 deletions libs/web-stub/src/stub/default-mock.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,59 @@
import { StubGenesisConfig } from "../types.js";

const zero = {
free: 0,
reserved: 0,
frozen: 0,
};

export default {
accounts: [
{
id: "5DD8bv4RnTDuJt47SAjpWMT78N7gfBQNF2YiZpVUgbXkizMG",
identity: {
legalName: "Alice",
display: "alice",
firstName: "Alice",
lastName: "Anon",
phone: "1.4168900514",
email: "[email protected]",
additional: [],
},
balance: 0,
balance: zero,
assets: {},
},
{
id: "5HVoCpiwRWMZCmM8ituz46JVGAzvAjqsHrGkdhqrDUD4NW6o",
identity: {
legalName: "Bob",
display: "bob",
firstName: "Bob",
lastName: "Bear",
phone: "1.4158900514",
email: "[email protected]",
additional: [],
},
balance: 0,
balance: zero,
assets: {},
},
],
events: [
{
id: 1,
owner: "5Fh3tNPUUKtApDZ6rJ2sDgcC5Z6pVVyAzKeE1dnqowLqWEvw",
name: "Dua Lipa en Colombia",
description: "Dua lipa viene a Colombia, no te lo pierdas",
banner:
"https://lumiere-a.akamaihd.net/v1/images/dua_lipa_portada_5_bf1628a4.jpeg?region=15,0,1956,1100&width=960",
dates: [
[1710446400000, 1710475200000],
[1710532800000, 1710561600000],
[1710619200000, 1710648000000],
],
date: [1710446400000, 1710475200000],
capacity: 24000,
},
{
id: 2,
owner: "5Fh3tNPUUKtApDZ6rJ2sDgcC5Z6pVVyAzKeE1dnqowLqWEvw",
name: "Mitú",
description: "Mitú Astra Tour 2023\n\nCon Charlie Florez, Varez y Puerto",
banner:
Expand All @@ -32,7 +63,7 @@ export default {
date: [1709762400000, 1709776800000],
},
{
id: 2,
id: 3,
owner: "5Fh3tNPUUKtApDZ6rJ2sDgcC5Z6pVVyAzKeE1dnqowLqWEvw",
name: "Dlina Volny",
description:
Expand All @@ -44,7 +75,7 @@ export default {
date: [1712345600000, 1712360000000],
},
{
id: 3,
id: 4,
owner: "5Fh3tNPUUKtApDZ6rJ2sDgcC5Z6pVVyAzKeE1dnqowLqWEvw",
name: "Paula Garcés - Laura Villalobos - Martin Arc - BT.MKR",
description:
Expand All @@ -56,12 +87,12 @@ export default {
},
],
tickets: [
// Event: Mitú
// Event: Dua Lipa en Colombia
{
id: 1,
issuer: 1,
owner: "5DD8bv4RnTDuJt47SAjpWMT78N7gfBQNF2YiZpVUgbXkizMG",
name: "Mitú",
name: "Dua Lipa en Colombia",
description: "General Entrance",
ticketArt:
"https://wild-presenta.com/wp-content/uploads/2023/07/MITU-ASTRATOURTUNJA19AGOSTO.jpg",
Expand All @@ -75,7 +106,7 @@ export default {
id: 2,
issuer: 1,
owner: "5HVoCpiwRWMZCmM8ituz46JVGAzvAjqsHrGkdhqrDUD4NW6o",
name: "Mitú",
name: "Dua Lipa en Colombia",
description: "General Entrance",
ticketArt:
"https://wild-presenta.com/wp-content/uploads/2023/07/MITU-ASTRATOURTUNJA19AGOSTO.jpg",
Expand All @@ -85,12 +116,12 @@ export default {
type: "Single",
},
},
// Event: Dlina Volny
// Event: Mitú
{
id: 1,
issuer: 2,
owner: "5DD8bv4RnTDuJt47SAjpWMT78N7gfBQNF2YiZpVUgbXkizMG",
name: "Dlina Volny",
name: "Mitú",
ticketArt:
"https://wild-presenta.com/wp-content/uploads/2023/07/Copia-de-FINAL.jpg",
description: "General Entrance",
Expand All @@ -104,7 +135,7 @@ export default {
id: 2,
issuer: 2,
owner: "5HVoCpiwRWMZCmM8ituz46JVGAzvAjqsHrGkdhqrDUD4NW6o",
name: "Dlina Volny",
name: "Mitú",
ticketArt:
"https://wild-presenta.com/wp-content/uploads/2023/07/Copia-de-FINAL.jpg",
description: "General Entrance",
Expand All @@ -114,11 +145,26 @@ export default {
type: "Single",
},
},
// Event: Paula Garcés - Laura Villalobos - Martin Arc - BT.MKR
// Event: Dlina Volny
{
id: 1,
issuer: 3,
owner: "5DD8bv4RnTDuJt47SAjpWMT78N7gfBQNF2YiZpVUgbXkizMG",
name: "Dlina Volny",
ticketArt:
"https://wild-presenta.com/wp-content/uploads/2024/01/FLYER.jpg",
description: "General Entrance",
attendances: [],
forSale: false,
attedancePolicy: {
type: "Single",
},
},
// Event: Paula Garcés - Laura Villalobos - Martin Arc - BT.MKR
{
id: 1,
issuer: 4,
owner: "5HVoCpiwRWMZCmM8ituz46JVGAzvAjqsHrGkdhqrDUD4NW6o",
name: "Paula Garcés - Laura Villalobos - Martin Arc - BT.MKR",
ticketArt:
"https://wild-presenta.com/wp-content/uploads/2024/01/FLYER.jpg",
Expand Down
27 changes: 19 additions & 8 deletions libs/web-stub/src/stub/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AccountId, Event, Get } from "@ticketto/types";
import { AccountId, Get } from "@ticketto/types";
import { Container, interfaces } from "inversify";
import { WebStubEventsCalls, WebStubEventsStorage } from "../events.js";
import { WebStubTicketsCalls, WebStubTicketsStorage } from "../tickets.js";
Expand All @@ -11,26 +11,32 @@ import {
StubGenesisConfig,
} from "../types.js";
import defaultMock from "./default-mock.js";
import {
WebStubDirectoryCalls,
WebStubDirectoryStorage,
} from "../directory.js";

export class Stub {
#accountProvider: ClientAccountProvider = {
sign(payload) {
return payload;
getAccountId() {
throw new Error("NotImplemented");
},
async sign() {
throw new Error("NotImplemented");
},
};
#container = new Container();

set accountProvider(accountProvider: ClientAccountProvider | undefined) {
withAccountProvider(accountProvider: ClientAccountProvider) {
if (accountProvider !== undefined) {
this.#accountProvider = accountProvider;
}

this.#container
.bind<Get<AccountId>>("Get<AccountId>")
.toConstantValue(
this.#accountProvider.getAccountId ??
(() => "5DD8bv4RnTDuJt47SAjpWMT78N7gfBQNF2YiZpVUgbXkizMG")
);
.toConstantValue(this.#accountProvider.getAccountId);

return this;
}

get accountProvider() {
Expand All @@ -49,6 +55,8 @@ export class Stub {
.bind<IDBPDatabase<TickettoDBSchema>>("TickettoDB")
.toConstantValue(database);

this.#container.bind(WebStubDirectoryCalls).to(WebStubDirectoryCalls);
this.#container.bind(WebStubDirectoryStorage).to(WebStubDirectoryStorage);
this.#container.bind(WebStubEventsCalls).to(WebStubEventsCalls);
this.#container.bind(WebStubEventsStorage).to(WebStubEventsStorage);
this.#container.bind(WebStubTicketsCalls).to(WebStubTicketsCalls);
Expand All @@ -65,6 +73,9 @@ export class Stub {
keyPath: "id",
});
accountsStore.createIndex("id", "id");
accountsStore.createIndex("display", "identity.display");
accountsStore.createIndex("phone", "identity.phone");
accountsStore.createIndex("email", "identity.email");

const eventsStore = db.createObjectStore("events", {
keyPath: "id",
Expand Down
9 changes: 2 additions & 7 deletions libs/web-stub/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
Account,
AccountId,
Event,
EventId,
Expand All @@ -9,12 +10,6 @@ import {

import { DBSchema } from "idb";

export type Account = {
id: AccountId;
identity: { legalName: string; email: string };
balance: number;
};

export type StubConsumerSettings = {
databaseName?: string;
genesisConfig?: StubGenesisConfig;
Expand All @@ -30,7 +25,7 @@ export interface TickettoDBSchema extends DBSchema {
accounts: {
key: AccountId;
value: Account;
indexes: { id: AccountId };
indexes: { id: AccountId; display: string; phone: string; email: string };
};
events: {
key: EventId;
Expand Down
8 changes: 8 additions & 0 deletions libs/web-stub/test/defaultConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { type ClientConfig } from "@ticketto/protocol";

export const defaultConfig: ClientConfig = {
accountProvider: {
getAccountId: () => "5DD8bv4RnTDuJt47SAjpWMT78N7gfBQNF2YiZpVUgbXkizMG",
sign: (payload) => Promise.resolve(payload),
},
};
Loading

0 comments on commit e737ed4

Please sign in to comment.