Add resolveCommitReferences method
This commit is contained in:
+72
-22
@@ -17,6 +17,7 @@ import type {
|
||||
XOInvitationOutput,
|
||||
XOInvitationVariable,
|
||||
XOInvitationVariableValue,
|
||||
XOTemplate,
|
||||
} from "@xo-cash/types";
|
||||
import type { UnspentOutputData } from "@xo-cash/state";
|
||||
import {
|
||||
@@ -34,8 +35,14 @@ import type { BlockchainService } from "./electrum.js";
|
||||
|
||||
import { EventEmitter } from "../utils/event-emitter.js";
|
||||
import { decodeExtendedJsonObject } from "../utils/ext-json.js";
|
||||
import {
|
||||
resolveCommitReferences,
|
||||
type ResolvedInvitationData,
|
||||
} from "../utils/resolve-invitation-data.js";
|
||||
import { compileCashAssemblyString } from "@xo-cash/engine";
|
||||
|
||||
export type { ResolvedInvitationData } from "../utils/resolve-invitation-data.js";
|
||||
|
||||
export type InvitationEventMap = {
|
||||
"invitation-updated": XOInvitation;
|
||||
"invitation-status-changed": string;
|
||||
@@ -103,11 +110,33 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
);
|
||||
|
||||
// Create the invitation
|
||||
const invitationInstance = new Invitation(engineInvitation, dependencies);
|
||||
const invitationInstance = new Invitation(
|
||||
engineInvitation,
|
||||
dependencies,
|
||||
template,
|
||||
);
|
||||
|
||||
return invitationInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattened, template-enriched view of {@link Invitation.data}.
|
||||
* Updated automatically whenever invitation data changes.
|
||||
*/
|
||||
public resolvedData: ResolvedInvitationData = {
|
||||
invitationIdentifier: "",
|
||||
templateIdentifier: "",
|
||||
actionIdentifier: "",
|
||||
variables: [],
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
};
|
||||
|
||||
/**
|
||||
* The template used to enrich {@link resolvedData}.
|
||||
*/
|
||||
private template: XOTemplate;
|
||||
|
||||
/**
|
||||
* The invitation data.
|
||||
*/
|
||||
@@ -145,14 +174,19 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
/**
|
||||
* Create an invitation and start the SSE Session required for it.
|
||||
*/
|
||||
constructor(invitation: XOInvitation, dependencies: InvitationDependencies) {
|
||||
constructor(
|
||||
invitation: XOInvitation,
|
||||
dependencies: InvitationDependencies,
|
||||
template: XOTemplate,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.data = invitation;
|
||||
this.template = template;
|
||||
this.engine = dependencies.engine;
|
||||
this.syncServer = dependencies.syncServer;
|
||||
this.storage = dependencies.storage;
|
||||
this.electrum = dependencies.electrum;
|
||||
this.updateInvitationData(invitation);
|
||||
|
||||
// Apply SSE updates serially so each engine update sees the latest history.
|
||||
this.syncServer.on("message", (event) => {
|
||||
@@ -167,6 +201,14 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates raw invitation data and recomputes {@link resolvedData}.
|
||||
*/
|
||||
private updateInvitationData(invitation: XOInvitation): void {
|
||||
this.data = invitation;
|
||||
this.resolvedData = resolveCommitReferences(invitation, this.template);
|
||||
}
|
||||
|
||||
private enqueueSyncUpdate(update: () => Promise<void>): Promise<void> {
|
||||
const queuedUpdate = this.sseUpdateQueue.then(update);
|
||||
this.sseUpdateQueue = queuedUpdate.catch(() => {});
|
||||
@@ -197,19 +239,21 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
|
||||
try {
|
||||
// Prefer keeping the engine's local invitation state in sync.
|
||||
this.data = stripLocalInvitationMetadata(
|
||||
await this.engine.updateInvitation({
|
||||
...this.data,
|
||||
...invitation,
|
||||
commits: combinedCommits,
|
||||
}),
|
||||
this.updateInvitationData(
|
||||
stripLocalInvitationMetadata(
|
||||
await this.engine.updateInvitation({
|
||||
...this.data,
|
||||
...invitation,
|
||||
commits: combinedCommits,
|
||||
}),
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
this.emit(
|
||||
"error",
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
);
|
||||
this.data = { ...this.data, commits: combinedCommits };
|
||||
this.updateInvitationData({ ...this.data, commits: combinedCommits });
|
||||
}
|
||||
|
||||
await this.storage.set(this.data.invitationIdentifier, this.data);
|
||||
@@ -243,19 +287,21 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
const newCommits = this.mergeCommits(this.data.commits, invitation.commits);
|
||||
|
||||
try {
|
||||
this.data = stripLocalInvitationMetadata(
|
||||
await this.engine.updateInvitation({
|
||||
...this.data,
|
||||
...invitation,
|
||||
commits: newCommits,
|
||||
}),
|
||||
this.updateInvitationData(
|
||||
stripLocalInvitationMetadata(
|
||||
await this.engine.updateInvitation({
|
||||
...this.data,
|
||||
...invitation,
|
||||
commits: newCommits,
|
||||
}),
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
this.emit(
|
||||
"error",
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
);
|
||||
this.data = { ...this.data, commits: newCommits };
|
||||
this.updateInvitationData({ ...this.data, commits: newCommits });
|
||||
}
|
||||
|
||||
await this.storage.set(this.data.invitationIdentifier, this.data);
|
||||
@@ -488,7 +534,9 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
*/
|
||||
async accept(acceptParams?: InvitationParameters): Promise<void> {
|
||||
// Accept the invitation
|
||||
this.data = await this.engine.acceptInvitation(this.data, acceptParams);
|
||||
this.updateInvitationData(
|
||||
await this.engine.acceptInvitation(this.data, acceptParams),
|
||||
);
|
||||
|
||||
// Sync the invitation to the sync server
|
||||
await this.publishInvitation(this.data);
|
||||
@@ -529,7 +577,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
// Store the signed invitation in the storage
|
||||
await this.storage.set(this.data.invitationIdentifier, signedInvitation);
|
||||
|
||||
this.data = signedInvitation;
|
||||
this.updateInvitationData(signedInvitation);
|
||||
|
||||
// Update the status of the invitation
|
||||
await this.updateStatus();
|
||||
@@ -563,9 +611,11 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
||||
await this.ensureAccepted();
|
||||
|
||||
// Append the commit to the invitation
|
||||
this.data = await this.engine.appendInvitation(
|
||||
this.data.invitationIdentifier,
|
||||
data,
|
||||
this.updateInvitationData(
|
||||
await this.engine.appendInvitation(
|
||||
this.data.invitationIdentifier,
|
||||
data,
|
||||
),
|
||||
);
|
||||
|
||||
// Sync the invitation to the sync server
|
||||
|
||||
Reference in New Issue
Block a user