import { RxCollection, RxDocument, RxJsonSchema } from "rxdb" import { Observable, merge, from } from "rxjs" import { map, switchMap, // startWith, // throttleTime, take, skip, debounceTime, startWith, throttleTime, } from "rxjs/operators" import { MetaverseLightwalletDatabase } from "./database" export interface OutputDocType { txid: string index: number attachment: any, script: string, height?: number, spent: boolean, address?: string, value: number, } export type OutputDocMethods = {} export type OutputDocument = RxDocument< OutputDocType, OutputDocMethods > export type OutputCollection = RxCollection< OutputDocType, OutputDocMethods, OutputCollectionMethods > export type OutputCollectionMethods = { count$: () => Observable countAll: () => Promise watch$: (debounce?: number) => Observable[]> utxos$: (addresses$: Observable, debounce?: number) => Observable clear: () => Promise, } export async function initOutputCollection( database: MetaverseLightwalletDatabase, ): Promise { const outputCollection = await database.collection< OutputDocType, OutputDocMethods, OutputCollectionMethods >({ name: "outputs", schema: outputSchema, methods: {}, statics: outputCollectionMethods, }) return outputCollection } export const outputCollectionMethods: OutputCollectionMethods = { count$: function (this: OutputCollection) { return this.find().$.pipe(map((txs) => txs.length)) }, countAll: async function (this: OutputCollection) { const allDocs = await this.find().exec() return allDocs.length }, watch$: function (this: OutputCollection, debounce = 2000) { return merge( this.$.pipe(take(1), startWith(0), switchMap(() => from(this.find().exec()))), this.$.pipe(skip(1), debounceTime(debounce), switchMap(() => this.find().$)), ) }, utxos$: function (this: OutputCollection, addresses$: Observable, debounce = 2000) { return addresses$.pipe( switchMap(addresses => this.find({ selector: { spent: false, address: { $in: addresses } }, }).$.pipe( throttleTime(debounce), map(utxos => utxos.map(utxo => utxo.toJSON())) )) ) }, clear: async function (this: OutputCollection) { const deleted = await this.find().remove() return deleted.length }, } export const outputSchema: RxJsonSchema = { title: "output", version: 0, description: "Metaverse output", type: "object", indexes: ["height", ["txid", "index"], ["spent", "address"]], properties: { txid: { type: "string", }, index: { type: "integer", }, attachment: { type: "object", }, height: { type: "integer", }, script: { type: "string", }, spent: { type: 'boolean', }, address: { type: "string", default: "", }, value: { type: "integer", }, }, }