Completely broken update to latest versions
This commit is contained in:
@@ -105,7 +105,7 @@ export class AppService extends EventEmitter<AppEventMap> {
|
|||||||
|
|
||||||
templates.forEach(async (template) => {
|
templates.forEach(async (template) => {
|
||||||
// engine.updateUnspentOutputsForTemplate(generateTemplateIdentifier(template));
|
// engine.updateUnspentOutputsForTemplate(generateTemplateIdentifier(template));
|
||||||
engine.subscribeToLockingBytecodesForTemplate(generateTemplateIdentifier(template));
|
engine.subscribeToScriptHashForTemplate(generateTemplateIdentifier(template));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,11 +114,11 @@ export class AppService extends EventEmitter<AppEventMap> {
|
|||||||
// Set default locking parameters for P2PKH
|
// Set default locking parameters for P2PKH
|
||||||
// To my knowledge, this doesnt generate any lockscript, so discovery of funds will not work automatically.
|
// 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?
|
// TODO: Add discovery for funds in the first index? Or until we return 0 TXs?
|
||||||
await engine.setDefaultLockingParameters(
|
// await engine.setDefaultLockingParameters(
|
||||||
generateTemplateIdentifier(parseTemplate(p2pkhTemplate)),
|
// generateTemplateIdentifier(parseTemplate(p2pkhTemplate)),
|
||||||
"receiveOutput",
|
// "receiveOutput",
|
||||||
"receiver",
|
// "receiver",
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Create our own storage for the invitations
|
// Create our own storage for the invitations
|
||||||
const storage = await Storage.create(config.invitationStoragePath);
|
const storage = await Storage.create(config.invitationStoragePath);
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export class HistoryService {
|
|||||||
const templateIdentifiers = new Set<string>();
|
const templateIdentifiers = new Set<string>();
|
||||||
|
|
||||||
for (const utxo of allUtxos) {
|
for (const utxo of allUtxos) {
|
||||||
templateIdentifiers.add(utxo.templateIdentifier);
|
templateIdentifiers.add(utxo.scriptHash);
|
||||||
}
|
}
|
||||||
for (const invitation of this.invitations) {
|
for (const invitation of this.invitations) {
|
||||||
templateIdentifiers.add(invitation.data.templateIdentifier);
|
templateIdentifiers.add(invitation.data.templateIdentifier);
|
||||||
@@ -186,7 +186,7 @@ export class HistoryService {
|
|||||||
metadataIndex: WalletMetadataIndex,
|
metadataIndex: WalletMetadataIndex,
|
||||||
): Promise<UtxoContext> {
|
): Promise<UtxoContext> {
|
||||||
const scriptHashData = metadataIndex.scriptHashDataByScriptHash.get(utxo.scriptHash);
|
const scriptHashData = metadataIndex.scriptHashDataByScriptHash.get(utxo.scriptHash);
|
||||||
const templateIdentifier = scriptHashData?.templateIdentifier ?? utxo.templateIdentifier;
|
const templateIdentifier = scriptHashData?.templateIdentifier!;
|
||||||
const template = (await this.engine.getTemplate(templateIdentifier)) ?? null;
|
const template = (await this.engine.getTemplate(templateIdentifier)) ?? null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -299,7 +299,7 @@ export class HistoryService {
|
|||||||
if (!matchingContext) continue;
|
if (!matchingContext) continue;
|
||||||
|
|
||||||
const lockingBytecode = this.getOutputLockingBytecodeHex(output) ?? matchingContext.scriptHashData?.lockingBytecode;
|
const lockingBytecode = this.getOutputLockingBytecodeHex(output) ?? matchingContext.scriptHashData?.lockingBytecode;
|
||||||
const outputIdentifier = output.outputIdentifier ?? matchingContext.scriptHashData?.outputIdentifier ?? matchingContext.utxo.outputIdentifier;
|
const outputIdentifier = output.outputIdentifier ?? matchingContext.scriptHashData?.outputIdentifier;
|
||||||
const role =
|
const role =
|
||||||
output.roleIdentifier ??
|
output.roleIdentifier ??
|
||||||
this.getFirstEntityRole(entityRoles, commit.entityIdentifier) ??
|
this.getFirstEntityRole(entityRoles, commit.entityIdentifier) ??
|
||||||
@@ -380,20 +380,21 @@ export class HistoryService {
|
|||||||
if (usedUtxoIds.has(this.getUtxoId(context.utxo))) return false;
|
if (usedUtxoIds.has(this.getUtxoId(context.utxo))) return false;
|
||||||
if (scriptHash && context.utxo.scriptHash === scriptHash) return true;
|
if (scriptHash && context.utxo.scriptHash === scriptHash) return true;
|
||||||
if (lockingBytecode && context.scriptHashData?.lockingBytecode === lockingBytecode) return true;
|
if (lockingBytecode && context.scriptHashData?.lockingBytecode === lockingBytecode) return true;
|
||||||
if (output.outputIdentifier && context.utxo.outputIdentifier === output.outputIdentifier) return true;
|
|
||||||
|
if (output.outputIdentifier && context.scriptHashData?.outputIdentifier === output.outputIdentifier) return true;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private projectStandaloneUtxo(context: UtxoContext): WalletHistoryItem {
|
private projectStandaloneUtxo(context: UtxoContext): WalletHistoryItem {
|
||||||
const output = this.projectUtxoOutput(context);
|
const output = this.projectUtxoOutput(context);
|
||||||
const templateIdentifier = context.scriptHashData?.templateIdentifier ?? context.utxo.templateIdentifier;
|
const templateIdentifier = context.scriptHashData?.templateIdentifier;
|
||||||
const role = output.role;
|
const role = output.role;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: `utxo-${context.utxo.outpointTransactionHash}:${context.utxo.outpointIndex}`,
|
id: `utxo-${context.utxo.outpointTransactionHash}:${context.utxo.outpointIndex}`,
|
||||||
source: "utxo",
|
source: "utxo",
|
||||||
templateIdentifier,
|
templateIdentifier: templateIdentifier ?? "",
|
||||||
template: context.template?.name ?? "UnknownTemplate",
|
template: context.template?.name ?? "UnknownTemplate",
|
||||||
roles: role ? [role] : ["unknown"],
|
roles: role ? [role] : ["unknown"],
|
||||||
description: output.description,
|
description: output.description,
|
||||||
@@ -404,7 +405,7 @@ export class HistoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private projectUtxoOutput(context: UtxoContext): WalletHistoryOutput {
|
private projectUtxoOutput(context: UtxoContext): WalletHistoryOutput {
|
||||||
const outputIdentifier = context.scriptHashData?.outputIdentifier ?? context.utxo.outputIdentifier;
|
const outputIdentifier = context.scriptHashData?.outputIdentifier;
|
||||||
const role = context.scriptHashData?.roleIdentifier;
|
const role = context.scriptHashData?.roleIdentifier;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -557,7 +558,7 @@ export class HistoryService {
|
|||||||
variables: Record<string, XOInvitationVariableValue>,
|
variables: Record<string, XOInvitationVariableValue>,
|
||||||
): string {
|
): string {
|
||||||
try {
|
try {
|
||||||
return compileCashAssemblyString(description, variables);
|
return compileCashAssemblyString({ cashAssemblyText: description, variables, evaluationDecodeMode: 'utf8' });
|
||||||
} catch {
|
} catch {
|
||||||
return this.interpolateSimpleCashAssemblyVariables(description, variables);
|
return this.interpolateSimpleCashAssemblyVariables(description, variables);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ import type {
|
|||||||
} from "@xo-cash/types";
|
} from "@xo-cash/types";
|
||||||
import type { UnspentOutputData } from "@xo-cash/state";
|
import type { UnspentOutputData } from "@xo-cash/state";
|
||||||
import {
|
import {
|
||||||
|
bigIntToBinUint64LE,
|
||||||
|
bigIntToBinUintBE,
|
||||||
|
bigIntToBinUintLE,
|
||||||
|
bigIntToVmNumber,
|
||||||
binToHex,
|
binToHex,
|
||||||
encodeTransaction,
|
encodeTransaction,
|
||||||
generateTransaction,
|
generateTransaction,
|
||||||
@@ -28,7 +32,7 @@ import type { BaseStorage } from "./storage.js";
|
|||||||
import type { BlockchainService } from "./electrum.js";
|
import type { BlockchainService } from "./electrum.js";
|
||||||
|
|
||||||
import { EventEmitter } from "../utils/event-emitter.js";
|
import { EventEmitter } from "../utils/event-emitter.js";
|
||||||
import { decodeExtendedJsonObject } from "../utils/ext-json.js";
|
import { decodeExtendedJson, decodeExtendedJsonObject, encodeExtendedJson } from "../utils/ext-json.js";
|
||||||
import { compileCashAssemblyString } from "@xo-cash/engine";
|
import { compileCashAssemblyString } from "@xo-cash/engine";
|
||||||
|
|
||||||
export type InvitationEventMap = {
|
export type InvitationEventMap = {
|
||||||
@@ -279,7 +283,8 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
private async computeStatusInternal(): Promise<string> {
|
private async computeStatusInternal(): Promise<string> {
|
||||||
let missingReqs;
|
let missingReqs;
|
||||||
try {
|
try {
|
||||||
missingReqs = await this.engine.listMissingRequirements(this.data);
|
const missingRequirements = await this.engine.listMissingRequirements(this.data.invitationIdentifier);
|
||||||
|
missingReqs = missingRequirements.templateRequirements;
|
||||||
} catch {
|
} catch {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
@@ -394,7 +399,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
*/
|
*/
|
||||||
async sign(): Promise<void> {
|
async sign(): Promise<void> {
|
||||||
// Sign the invitation
|
// Sign the invitation
|
||||||
const signedInvitation = await this.engine.signInvitation(this.data);
|
const signedInvitation = await this.engine.signInvitation(this.data.invitationIdentifier);
|
||||||
|
|
||||||
// Publish the signed invitation to the sync server
|
// Publish the signed invitation to the sync server
|
||||||
this.publishInvitation(signedInvitation);
|
this.publishInvitation(signedInvitation);
|
||||||
@@ -413,7 +418,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
* @returns The transaction hash returned by the network after broadcast.
|
* @returns The transaction hash returned by the network after broadcast.
|
||||||
*/
|
*/
|
||||||
async broadcast(): Promise<string> {
|
async broadcast(): Promise<string> {
|
||||||
const txHash = await this.engine.executeAction(this.data, {
|
const txHash = await this.engine.executeAction(this.data.invitationIdentifier, {
|
||||||
broadcastTransaction: true,
|
broadcastTransaction: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -431,7 +436,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
*/
|
*/
|
||||||
async append(data: AppendInvitationParameters): Promise<void> {
|
async append(data: AppendInvitationParameters): Promise<void> {
|
||||||
// Append the commit to the invitation
|
// Append the commit to the invitation
|
||||||
this.data = await this.engine.appendInvitation(this.data, data);
|
this.data = await this.engine.appendInvitation(this.data.invitationIdentifier, data);
|
||||||
|
|
||||||
// Sync the invitation to the sync server
|
// Sync the invitation to the sync server
|
||||||
await this.publishInvitation(this.data);
|
await this.publishInvitation(this.data);
|
||||||
@@ -546,7 +551,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
* Get the missing requirements for the invitation
|
* Get the missing requirements for the invitation
|
||||||
*/
|
*/
|
||||||
async getMissingRequirements() {
|
async getMissingRequirements() {
|
||||||
return this.engine.listMissingRequirements(this.data);
|
return this.engine.listMissingRequirements(this.data.invitationIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -608,33 +613,41 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const valueSatoshisIdentifier = output.valueSatoshis;
|
const valueSatoshisExpression = output.valueSatoshis;
|
||||||
if (!valueSatoshisIdentifier) {
|
if (!valueSatoshisExpression) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Value satoshis identifier not found: ${outputIdentifier} in template: ${this.data.templateIdentifier}`,
|
`Value satoshis identifier not found: ${outputIdentifier} in template: ${this.data.templateIdentifier}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.dir(this.data, { depth: null });
|
||||||
|
|
||||||
// Create a list of all the variables from the commits
|
// Create a list of all the variables from the commits
|
||||||
const variables = this.data.commits.flatMap(
|
const variables = this.data.commits.flatMap(
|
||||||
(c) => c.data?.variables ?? [],
|
(c) => c.data?.variables ?? [],
|
||||||
);
|
);
|
||||||
|
console.dir(variables, { depth: null });
|
||||||
|
|
||||||
// Create a dictionary of the variables
|
// Create a dictionary of the variables
|
||||||
const formattedVariables = variables.reduce(
|
const formattedVariables = variables.reduce(
|
||||||
(acc, v) => {
|
(acc, v) => {
|
||||||
acc[v.variableIdentifier ?? ""] = v.value;
|
const { variableIdentifier, value } = v;
|
||||||
|
console.log(typeof value);
|
||||||
|
acc[variableIdentifier ?? ""] = value;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{} as Record<string, XOInvitationVariableValue>,
|
{} as Record<string, XOInvitationVariableValue>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.dir(formattedVariables, { depth: null });
|
||||||
|
|
||||||
// Compile the CashAssembly expression to get the value satoshis (It handles the variable replacement for us)
|
// Compile the CashAssembly expression to get the value satoshis (It handles the variable replacement for us)
|
||||||
const valueSatoshis = await compileCashAssemblyString(
|
const valueSatoshis = compileCashAssemblyString(
|
||||||
String(valueSatoshisIdentifier),
|
{ cashAssemblyText: String(valueSatoshisExpression), variables: formattedVariables, evaluationDecodeMode: 'bigint' },
|
||||||
formattedVariables,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.dir(valueSatoshis, { depth: null });
|
||||||
|
|
||||||
// Return the value satoshis as a bigint
|
// Return the value satoshis as a bigint
|
||||||
// TODO: Check this of a vulnerability or crash - I assume there might be one if someone made the `valueSatoshis` a malicious expression
|
// TODO: Check this of a vulnerability or crash - I assume there might be one if someone made the `valueSatoshis` a malicious expression
|
||||||
return BigInt(valueSatoshis);
|
return BigInt(valueSatoshis);
|
||||||
@@ -688,9 +701,13 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
// Iterate through the outputs and sum the valueSatoshis
|
// Iterate through the outputs and sum the valueSatoshis
|
||||||
for (const output of outputs) {
|
for (const output of outputs) {
|
||||||
if (typeof output === "string") {
|
if (typeof output === "string") {
|
||||||
totalSats += await this.getSatsOut(output);
|
const sats = await this.getSatsOut(output);
|
||||||
|
console.log(`Sats for output: ${output} is ${sats}`);
|
||||||
|
totalSats += sats
|
||||||
} else {
|
} else {
|
||||||
totalSats += await this.getSatsOut(output.output);
|
const sats = await this.getSatsOut(output.output);
|
||||||
|
console.log(`Sats for output: ${output.output} is ${sats}`);
|
||||||
|
totalSats += sats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export function InvitationScreen(): React.ReactElement {
|
|||||||
|
|
||||||
let isCurrent = true;
|
let isCurrent = true;
|
||||||
|
|
||||||
appService.engine.getOwnCommits(selectedInvitation.data)
|
appService.engine.findOwnCommits(selectedInvitation.data.invitationIdentifier)
|
||||||
.then((ownCommits) => {
|
.then((ownCommits) => {
|
||||||
if (!isCurrent) return;
|
if (!isCurrent) return;
|
||||||
|
|
||||||
@@ -723,10 +723,14 @@ export function InvitationScreen(): React.ReactElement {
|
|||||||
{outputTemplate?.name ?? output.outputIdentifier ?? `Output ${idx}`}
|
{outputTemplate?.name ?? output.outputIdentifier ?? `Output ${idx}`}
|
||||||
|
|
||||||
{/* Output description */}
|
{/* Output description */}
|
||||||
{outputTemplate?.description && ' - ' + compileCashAssemblyString(outputTemplate?.description ?? '', variables.reduce((acc, variable) => {
|
{outputTemplate?.description && ' - ' + compileCashAssemblyString({
|
||||||
acc[variable.variableIdentifier] = variable.value as XOInvitationVariableValue;
|
cashAssemblyText: outputTemplate?.description,
|
||||||
return acc;
|
variables: variables.reduce((acc, variable) => {
|
||||||
}, {} as Record<string, XOInvitationVariableValue>))}
|
acc[variable.variableIdentifier] = variable.value as XOInvitationVariableValue;
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, XOInvitationVariableValue>)
|
||||||
|
})}
|
||||||
|
|
||||||
{/* Output value */}
|
{/* Output value */}
|
||||||
{outputSatoshis !== null && ` (${formatSatoshis(outputSatoshis)}${getFiatSuffix(outputSatoshis)})`}
|
{outputSatoshis !== null && ` (${formatSatoshis(outputSatoshis)}${getFiatSuffix(outputSatoshis)})`}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const isInvitationRequirementsComplete = async (
|
|||||||
invitation: Invitation,
|
invitation: Invitation,
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
const missingRequirements = await invitation.getMissingRequirements();
|
const missingRequirements = await invitation.getMissingRequirements();
|
||||||
return !hasMissingRequirements(missingRequirements);
|
return !hasMissingRequirements(missingRequirements.templateRequirements);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Move to engine in templates.ts
|
// TODO: Move to engine in templates.ts
|
||||||
|
|||||||
Reference in New Issue
Block a user