Format with prettier. Use screen mode for invitation import - dialog mode is broken.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { XOTemplate, XOTemplateTransactionOutput } from '@xo-cash/types';
|
||||
import type { Invitation } from '../services/invitation.js';
|
||||
import type { XOTemplate, XOTemplateTransactionOutput } from "@xo-cash/types";
|
||||
import type { Invitation } from "../services/invitation.js";
|
||||
|
||||
export interface SelectableUtxoLike {
|
||||
outpointTransactionHash: string;
|
||||
@@ -16,14 +16,17 @@ export const hasMissingRequirements = (missingRequirements: {
|
||||
roles?: Record<string, unknown>;
|
||||
}): boolean => {
|
||||
return (
|
||||
(missingRequirements.variables?.length ?? 0) > 0
|
||||
|| (missingRequirements.inputs?.length ?? 0) > 0
|
||||
|| (missingRequirements.outputs?.length ?? 0) > 0
|
||||
|| (missingRequirements.roles !== undefined && Object.keys(missingRequirements.roles).length > 0)
|
||||
(missingRequirements.variables?.length ?? 0) > 0 ||
|
||||
(missingRequirements.inputs?.length ?? 0) > 0 ||
|
||||
(missingRequirements.outputs?.length ?? 0) > 0 ||
|
||||
(missingRequirements.roles !== undefined &&
|
||||
Object.keys(missingRequirements.roles).length > 0)
|
||||
);
|
||||
};
|
||||
|
||||
export const isInvitationRequirementsComplete = async (invitation: Invitation): Promise<boolean> => {
|
||||
export const isInvitationRequirementsComplete = async (
|
||||
invitation: Invitation,
|
||||
): Promise<boolean> => {
|
||||
const missingRequirements = await invitation.getMissingRequirements();
|
||||
return !hasMissingRequirements(missingRequirements);
|
||||
};
|
||||
@@ -34,7 +37,7 @@ export const resolveActionRoles = (
|
||||
rolesFromNavigation?: string[],
|
||||
): string[] => {
|
||||
if (rolesFromNavigation && rolesFromNavigation.length > 0) {
|
||||
return [ ...new Set(rolesFromNavigation) ];
|
||||
return [...new Set(rolesFromNavigation)];
|
||||
}
|
||||
|
||||
if (!template || !actionIdentifier) return [];
|
||||
@@ -43,7 +46,7 @@ export const resolveActionRoles = (
|
||||
.filter((entry) => entry.action === actionIdentifier)
|
||||
.map((entry) => entry.role);
|
||||
|
||||
return [ ...new Set(roleIds) ];
|
||||
return [...new Set(roleIds)];
|
||||
};
|
||||
|
||||
export const roleRequiresInputs = (
|
||||
@@ -61,26 +64,38 @@ export const roleRequiresInputs = (
|
||||
|
||||
// Some templates specify slot/input requirements at action.requirements.roles
|
||||
// instead of role.requirements. Respect those as well.
|
||||
const roleRequirement = action.requirements?.roles?.find((requirement) => requirement.role === roleIdentifier);
|
||||
const roleRequirement = action.requirements?.roles?.find(
|
||||
(requirement) => requirement.role === roleIdentifier,
|
||||
);
|
||||
const actionLevelSlotsMin = roleRequirement?.slots?.min ?? 0;
|
||||
if (actionLevelSlotsMin > 0) return true;
|
||||
|
||||
const transactionIdentifier = action.transaction;
|
||||
const transaction = transactionIdentifier ? template.transactions?.[transactionIdentifier] : undefined;
|
||||
const transaction = transactionIdentifier
|
||||
? template.transactions?.[transactionIdentifier]
|
||||
: undefined;
|
||||
const roleInputs = transaction?.roles?.[roleIdentifier]?.inputs;
|
||||
|
||||
return (roleInputs?.length ?? 0) > 0;
|
||||
};
|
||||
|
||||
export const getTransactionOutputIdentifier = (output: XOTemplateTransactionOutput): string | undefined => {
|
||||
if (typeof output === 'string') return output;
|
||||
if (output && typeof output === 'object' && 'output' in output && typeof output.output === 'string') {
|
||||
export const getTransactionOutputIdentifier = (
|
||||
output: XOTemplateTransactionOutput,
|
||||
): string | undefined => {
|
||||
if (typeof output === "string") return output;
|
||||
if (
|
||||
output &&
|
||||
typeof output === "object" &&
|
||||
"output" in output &&
|
||||
typeof output.output === "string"
|
||||
) {
|
||||
return output.output;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const normalizeLockingBytecodeHex = (value: string): string => value.trim().replace(/^0x/i, '');
|
||||
export const normalizeLockingBytecodeHex = (value: string): string =>
|
||||
value.trim().replace(/^0x/i, "");
|
||||
|
||||
export const resolveProvidedLockingBytecodeHex = (
|
||||
template: XOTemplate,
|
||||
@@ -88,18 +103,23 @@ export const resolveProvidedLockingBytecodeHex = (
|
||||
variableValues: Record<string, string>,
|
||||
): string | undefined => {
|
||||
const outputDefinition = template.outputs?.[outputIdentifier];
|
||||
if (!outputDefinition || typeof outputDefinition.lockscript !== 'string') return undefined;
|
||||
if (!outputDefinition || typeof outputDefinition.lockscript !== "string")
|
||||
return undefined;
|
||||
|
||||
const lockingScriptDefinition = (template.lockingScripts as Record<string, unknown> | undefined)?.[outputDefinition.lockscript] as
|
||||
| { lockingScript?: string }
|
||||
| undefined;
|
||||
const lockingScriptDefinition = (
|
||||
template.lockingScripts as Record<string, unknown> | undefined
|
||||
)?.[outputDefinition.lockscript] as { lockingScript?: string } | undefined;
|
||||
const scriptIdentifier = lockingScriptDefinition?.lockingScript;
|
||||
if (!scriptIdentifier) return undefined;
|
||||
|
||||
const scriptExpression = (template.scripts as Record<string, unknown> | undefined)?.[scriptIdentifier];
|
||||
if (typeof scriptExpression !== 'string') return undefined;
|
||||
const scriptExpression = (
|
||||
template.scripts as Record<string, unknown> | undefined
|
||||
)?.[scriptIdentifier];
|
||||
if (typeof scriptExpression !== "string") return undefined;
|
||||
|
||||
const directVariableMatch = scriptExpression.match(/^<\s*([A-Za-z0-9_]+)\s*>$/);
|
||||
const directVariableMatch = scriptExpression.match(
|
||||
/^<\s*([A-Za-z0-9_]+)\s*>$/,
|
||||
);
|
||||
if (!directVariableMatch) return undefined;
|
||||
|
||||
const variableIdentifier = directVariableMatch[1];
|
||||
@@ -111,15 +131,17 @@ export const resolveProvidedLockingBytecodeHex = (
|
||||
return normalizeLockingBytecodeHex(providedValue);
|
||||
};
|
||||
|
||||
export const mapUnspentOutputsToSelectable = (unspentOutputs: any[]): SelectableUtxoLike[] => {
|
||||
export const mapUnspentOutputsToSelectable = (
|
||||
unspentOutputs: any[],
|
||||
): SelectableUtxoLike[] => {
|
||||
return unspentOutputs.map((utxo: any) => ({
|
||||
outpointTransactionHash: utxo.outpointTransactionHash,
|
||||
outpointIndex: utxo.outpointIndex,
|
||||
valueSatoshis: BigInt(utxo.valueSatoshis),
|
||||
lockingBytecode: utxo.lockingBytecode
|
||||
? typeof utxo.lockingBytecode === 'string'
|
||||
? typeof utxo.lockingBytecode === "string"
|
||||
? utxo.lockingBytecode
|
||||
: Buffer.from(utxo.lockingBytecode).toString('hex')
|
||||
: Buffer.from(utxo.lockingBytecode).toString("hex")
|
||||
: undefined,
|
||||
selected: false,
|
||||
}));
|
||||
@@ -133,7 +155,10 @@ export const autoSelectGreedyUtxos = (
|
||||
const seenLockingBytecodes = new Set<string>();
|
||||
|
||||
for (const utxo of utxos) {
|
||||
if (utxo.lockingBytecode && seenLockingBytecodes.has(utxo.lockingBytecode)) {
|
||||
if (
|
||||
utxo.lockingBytecode &&
|
||||
seenLockingBytecodes.has(utxo.lockingBytecode)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (utxo.lockingBytecode) {
|
||||
|
||||
Reference in New Issue
Block a user