Breaking-Change: Extremely rough update to work with Kioks wallet
This commit is contained in:
+7
-22
@@ -81,22 +81,7 @@ export class AppService extends EventEmitter<AppEventMap> {
|
||||
|
||||
// TODO: We *technically* dont want this here, but we also need some initial templates for the wallet, so im doing it here
|
||||
// Import the default P2PKH template
|
||||
const { templateIdentifier } = await engine.importTemplate(p2pkhTemplate);
|
||||
|
||||
// engine
|
||||
// .subscribeToLockingBytecodesForTemplate(templateIdentifier)
|
||||
// .catch((err) =>
|
||||
// console.error(
|
||||
// `Error subscribing to locking bytecodes for template ${templateIdentifier}: ${err}`,
|
||||
// ),
|
||||
// );
|
||||
// engine
|
||||
// .updateUnspentOutputsForTemplate(templateIdentifier)
|
||||
// .catch((err) =>
|
||||
// console.error(
|
||||
// `Error updating unspent outputs for template ${templateIdentifier}: ${err}`,
|
||||
// ),
|
||||
// );
|
||||
await engine.importTemplate(p2pkhTemplate);
|
||||
|
||||
// Update all the unspents for every template, and subscribe to the locking bytecodes for changes
|
||||
// TODO: Remove the above lines that do the same thing. Minimising changes for BLISS.
|
||||
@@ -104,7 +89,7 @@ export class AppService extends EventEmitter<AppEventMap> {
|
||||
const templates = await engine.listImportedTemplates();
|
||||
|
||||
templates.forEach(async (template) => {
|
||||
// engine.updateUnspentOutputsForTemplate(generateTemplateIdentifier(template));
|
||||
engine.updateUnspentOutputsForTemplate(generateTemplateIdentifier(template));
|
||||
engine.subscribeToScriptHashForTemplate(generateTemplateIdentifier(template));
|
||||
});
|
||||
};
|
||||
@@ -114,11 +99,11 @@ export class AppService extends EventEmitter<AppEventMap> {
|
||||
// Set default locking parameters for P2PKH
|
||||
// To my knowledge, this doesnt generate any lockscript, so discovery of funds will not work automatically.
|
||||
// TODO: Add discovery for funds in the first index? Or until we return 0 TXs?
|
||||
// await engine.setDefaultLockingParameters(
|
||||
// generateTemplateIdentifier(parseTemplate(p2pkhTemplate)),
|
||||
// "receiveOutput",
|
||||
// "receiver",
|
||||
// );
|
||||
await engine.setDefaultLockingParameters(
|
||||
generateTemplateIdentifier(parseTemplate(p2pkhTemplate)),
|
||||
"receiveOutput",
|
||||
"receiver",
|
||||
);
|
||||
|
||||
// Create our own storage for the invitations
|
||||
const storage = await Storage.create(config.invitationStoragePath);
|
||||
|
||||
+25
-9
@@ -1,6 +1,6 @@
|
||||
import { binToHex, hexToBin, sha256 } from "@bitauth/libauth";
|
||||
import { compileCashAssemblyString, type Engine } from "@xo-cash/engine";
|
||||
import type { ScriptHashData, UnspentOutputData } from "@xo-cash/state";
|
||||
import type { ScriptHashData, State, UnspentOutputData } from "@xo-cash/state";
|
||||
import type {
|
||||
XOInvitation,
|
||||
XOInvitationCommit,
|
||||
@@ -146,8 +146,10 @@ export class HistoryService {
|
||||
const contexts = new Map<string, InvitationContext>();
|
||||
|
||||
for (const invitation of this.invitations) {
|
||||
const template =
|
||||
(await this.engine.getTemplate(invitation.data.templateIdentifier)) ?? null;
|
||||
const templateIdentifier = invitation.data.templateIdentifier;
|
||||
const template = templateIdentifier
|
||||
? (await this.engine.getTemplate(templateIdentifier)) ?? null
|
||||
: null;
|
||||
contexts.set(invitation.data.invitationIdentifier, {
|
||||
invitation,
|
||||
template,
|
||||
@@ -164,11 +166,19 @@ export class HistoryService {
|
||||
const scriptHashDataByScriptHash = new Map<string, ScriptHashData>();
|
||||
const templateIdentifiers = new Set<string>();
|
||||
|
||||
for (const utxo of allUtxos) {
|
||||
templateIdentifiers.add(utxo.scriptHash);
|
||||
}
|
||||
for (const invitation of this.invitations) {
|
||||
templateIdentifiers.add(invitation.data.templateIdentifier);
|
||||
if (invitation.data.templateIdentifier) {
|
||||
templateIdentifiers.add(invitation.data.templateIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
const uniqueScriptHashes = new Set(allUtxos.map((utxo) => utxo.scriptHash));
|
||||
for (const scriptHash of uniqueScriptHashes) {
|
||||
const scriptHashData = await this.getScriptHashData(scriptHash);
|
||||
if (scriptHashData === undefined) continue;
|
||||
|
||||
scriptHashDataByScriptHash.set(scriptHash, scriptHashData);
|
||||
templateIdentifiers.add(scriptHashData.templateIdentifier);
|
||||
}
|
||||
|
||||
for (const templateIdentifier of templateIdentifiers) {
|
||||
@@ -186,8 +196,10 @@ export class HistoryService {
|
||||
metadataIndex: WalletMetadataIndex,
|
||||
): Promise<UtxoContext> {
|
||||
const scriptHashData = metadataIndex.scriptHashDataByScriptHash.get(utxo.scriptHash);
|
||||
const templateIdentifier = scriptHashData?.templateIdentifier!;
|
||||
const template = (await this.engine.getTemplate(templateIdentifier)) ?? null;
|
||||
const templateIdentifier = scriptHashData?.templateIdentifier;
|
||||
const template = templateIdentifier
|
||||
? (await this.engine.getTemplate(templateIdentifier)) ?? null
|
||||
: null;
|
||||
|
||||
return {
|
||||
utxo,
|
||||
@@ -592,6 +604,10 @@ export class HistoryService {
|
||||
: binToHex(output.lockingBytecode);
|
||||
}
|
||||
|
||||
private async getScriptHashData(scriptHash: string): Promise<ScriptHashData | undefined> {
|
||||
return (this.engine as unknown as { state: State }).state.getScriptHashData(scriptHash);
|
||||
}
|
||||
|
||||
private getOutpointKey(txid: string, index: number): string {
|
||||
return `${txid}:${index}`;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import type { BaseStorage } from "./storage.js";
|
||||
import type { BlockchainService } from "./electrum.js";
|
||||
|
||||
import { EventEmitter } from "../utils/event-emitter.js";
|
||||
import { decodeExtendedJson, decodeExtendedJsonObject, encodeExtendedJson } from "../utils/ext-json.js";
|
||||
import { decodeExtendedJsonObject } from "../utils/ext-json.js";
|
||||
import { compileCashAssemblyString } from "@xo-cash/engine";
|
||||
|
||||
export type InvitationEventMap = {
|
||||
@@ -154,6 +154,10 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
* Start the invitation - Connect sync server and download latest invitation data.
|
||||
*/
|
||||
async start(): Promise<void> {
|
||||
// Persist immediately so imports survive sync-server outages and appear in the TUI
|
||||
// after a CLI import or app restart.
|
||||
await this.storage.set(this.data.invitationIdentifier, this.data);
|
||||
|
||||
try {
|
||||
// Connect to the sync server and get the invitation (in parallel)
|
||||
const [_, invitation] = await Promise.all([
|
||||
|
||||
+11
-11
@@ -1,5 +1,6 @@
|
||||
import Database from "better-sqlite3";
|
||||
import { decodeExtendedJson, encodeExtendedJson } from "../utils/ext-json.js";
|
||||
import { deserializeInvitation, serializeInvitation } from "@xo-cash/engine";
|
||||
import type { XOInvitation } from "@xo-cash/types";
|
||||
|
||||
/**
|
||||
* This is not an actual storage adapter that we want to make use of. This storage adapter is a stop-gap while the engine is under development.
|
||||
@@ -56,9 +57,8 @@ export class Storage extends BaseStorage {
|
||||
return fullKey.startsWith(prefix) ? fullKey.slice(prefix.length) : fullKey;
|
||||
}
|
||||
|
||||
async set(key: string, value: any): Promise<void> {
|
||||
// Encode the extended json object
|
||||
const encodedValue = encodeExtendedJson(value);
|
||||
async set(key: string, value: XOInvitation): Promise<void> {
|
||||
const encodedValue = serializeInvitation(value);
|
||||
|
||||
// Insert or replace the value into the database with full key (including basePath)
|
||||
const fullKey = this.getFullKey(key);
|
||||
@@ -93,10 +93,10 @@ export class Storage extends BaseStorage {
|
||||
return !strippedKey.includes(".");
|
||||
});
|
||||
|
||||
// Decode the extended json objects and strip basePath from keys
|
||||
// Deserialize invitations and strip basePath from keys
|
||||
return filteredRows.map((row) => ({
|
||||
key: this.stripBasePath(row.key),
|
||||
value: decodeExtendedJson(row.value),
|
||||
value: deserializeInvitation(row.value),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ export class Storage extends BaseStorage {
|
||||
if (!row) return null;
|
||||
|
||||
// Decode the extended json object
|
||||
return decodeExtendedJson(row.value);
|
||||
return deserializeInvitation(row.value);
|
||||
}
|
||||
|
||||
async remove(key: string): Promise<void> {
|
||||
@@ -174,9 +174,9 @@ export class InMemoryStorage extends BaseStorage {
|
||||
return fullKey.startsWith(prefix) ? fullKey.slice(prefix.length) : fullKey;
|
||||
}
|
||||
|
||||
async set(key: string, value: any): Promise<void> {
|
||||
async set(key: string, value: XOInvitation): Promise<void> {
|
||||
const fullKey = this.getFullKey(key);
|
||||
const encodedValue = encodeExtendedJson(value);
|
||||
const encodedValue = serializeInvitation(value);
|
||||
this.store.set(fullKey, encodedValue);
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ export class InMemoryStorage extends BaseStorage {
|
||||
|
||||
return filteredRows.map((row) => ({
|
||||
key: this.stripBasePath(row.key),
|
||||
value: decodeExtendedJson(row.value),
|
||||
value: deserializeInvitation(row.value),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ export class InMemoryStorage extends BaseStorage {
|
||||
const encodedValue = this.store.get(fullKey);
|
||||
if (encodedValue === undefined) return null;
|
||||
|
||||
return decodeExtendedJson(encodedValue);
|
||||
return deserializeInvitation(encodedValue);
|
||||
}
|
||||
|
||||
async remove(key: string): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user