241 lines
8.4 KiB
TypeScript
241 lines
8.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
import type { XOInvitation } from "@xo-cash/types";
|
||
|
||
import { vendingMachineTemplate } from "../../src/templates/vending-machine.js";
|
||
import { resolveCommitReferences } from "../../src/utils/resolve-invitation-data.js";
|
||
|
||
const MERCHANT_ENTITY =
|
||
"xpub6EUk69HMQk83Ay3QEFWhYgvqLvT6tGTnzWK33fao2fvnDyzhbBeoSc6JbQkvnKq33bH7HjqQmZ9H29hsesC53ZgxQfGBadBZL5jmSa7kbTD";
|
||
const CUSTOMER_ENTITY =
|
||
"xpub6FHRsCb1ma6VFGZpRYZL8A3X1Gwwc8JjRcaDJR2vgirrttmdvJX5VNYceA84RDVjy1c2a2oYEwuayLDZ9gssDgU52UXDGFTDa19z5ceXfFh";
|
||
|
||
/**
|
||
* Minimal reproduction of OriginalInvitation.json for the vending machine flow.
|
||
*/
|
||
const originalInvitation: XOInvitation = {
|
||
invitationIdentifier: "c57b1f8f8534df28b359e323c5fbd5ba",
|
||
createdAtTimestamp: 1779488689379,
|
||
templateIdentifier:
|
||
"feadd05c6566c5eded68f321efe7150cb765fda070d027c89f285e5b42a00652",
|
||
actionIdentifier: "purchaseItems",
|
||
commits: [
|
||
{
|
||
commitIdentifier: "76b935a35ca45f1065f9c66769d1a957",
|
||
previousCommitIdentifier: undefined,
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
data: {},
|
||
signature: "5f487c045657f3939ecfeaaacf239a7cfd44b485c2be591f5280bf0cc3a6e5fe304e8ea23311d82b2afa4f0ad7e0a6d07ec1e0b1aaee9c44097613694390966b",
|
||
expiresAtTimestamp: 1779506689379,
|
||
},
|
||
{
|
||
commitIdentifier: "cbf2d6242144f6761d0efc3bbbbf6660",
|
||
previousCommitIdentifier: "76b935a35ca45f1065f9c66769d1a957",
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
data: {
|
||
variables: [
|
||
{
|
||
variableIdentifier: "totalSatoshis",
|
||
roleIdentifier: "merchant",
|
||
value: 3000,
|
||
},
|
||
{
|
||
variableIdentifier: "orderId",
|
||
roleIdentifier: "merchant",
|
||
value: "eb5a30b3-ec8c-4b81-89dd-c53371f55a0e",
|
||
},
|
||
{
|
||
variableIdentifier: "merchantName",
|
||
roleIdentifier: "merchant",
|
||
value: "XO Snack Machine",
|
||
},
|
||
{
|
||
variableIdentifier: "receiptSummary",
|
||
roleIdentifier: "merchant",
|
||
value: "2× Chips",
|
||
},
|
||
{
|
||
variableIdentifier: "lineItemsJson",
|
||
roleIdentifier: "merchant",
|
||
value:
|
||
'[{"id":"225e37f4-14f2-4b33-86fd-763018bbfd7c","name":"Chips","quantity":2,"price":1500}]',
|
||
},
|
||
],
|
||
},
|
||
signature: "7cfc53860ec81403a79a03521a7674ee8d2a11365ee031e4f7f2e36a045bd6e2999510264b29045582a74e1190f0176950a855361f02bc67ff7877fabcf794f4",
|
||
expiresAtTimestamp: 1779506689390,
|
||
},
|
||
{
|
||
commitIdentifier: "583208aa304c0aa9841d1400efe6b6aa",
|
||
previousCommitIdentifier: "cbf2d6242144f6761d0efc3bbbbf6660",
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
data: {
|
||
outputs: [
|
||
{
|
||
outputIdentifier: "purchaseOutput",
|
||
lockingBytecode:
|
||
"76a9146a4715fe1cc1ce228336502f1711b06045ef361088ac",
|
||
},
|
||
],
|
||
},
|
||
signature: "d9bdd3b24fef6afd13f12da92e832672c6c1b83fb372506faeb7fa4ea0e39e3a32ad74493fbe7a393aed58bc18226431dabae09948ce371ad3f77b0219cb3831",
|
||
expiresAtTimestamp: 1779506689412,
|
||
},
|
||
{
|
||
commitIdentifier: "4f3f9a3361c8070ab589cc44248a6a80",
|
||
previousCommitIdentifier: "583208aa304c0aa9841d1400efe6b6aa",
|
||
entityIdentifier: CUSTOMER_ENTITY,
|
||
data: {},
|
||
signature: "63be8af81622da4fccc7eb6b81c6174879fe6aa113b8dae794bd42d4d5c87ae550a18be1e6cb5edf231e774bdc7883eb5a78bd02188579dce58da0d449c43865",
|
||
expiresAtTimestamp: 1779506979194,
|
||
},
|
||
{
|
||
commitIdentifier: "d18b9a0caa638eaa1d0711f333e9c114",
|
||
previousCommitIdentifier: "4f3f9a3361c8070ab589cc44248a6a80",
|
||
entityIdentifier: CUSTOMER_ENTITY,
|
||
data: {
|
||
inputs: [
|
||
{
|
||
outpointTransactionHash:
|
||
"b1e8f77cdc60efac19f668fc5c7177ace42a46e2532f230979559c7190c3c80a",
|
||
outpointIndex: 1,
|
||
},
|
||
],
|
||
},
|
||
signature: "e36942eb5f147e620659d20b7059630da871944e74fe5ffb3c4ff0298a5aedb101bc7468b19750114cbcfa56b99bd4a080453a31084f18173adcd9442fca4303",
|
||
expiresAtTimestamp: 1779507006272,
|
||
},
|
||
{
|
||
commitIdentifier: "7823f7ae7a365f87f6acdfee8896f508",
|
||
previousCommitIdentifier: "d18b9a0caa638eaa1d0711f333e9c114",
|
||
entityIdentifier: CUSTOMER_ENTITY,
|
||
data: {
|
||
outputs: [
|
||
{
|
||
valueSatoshis: 74881n,
|
||
lockingBytecode:
|
||
"76a9141730ca066d4b9c8d542f8c9bdce645f77697d46088ac",
|
||
},
|
||
],
|
||
},
|
||
signature: "2c1d1ed1259a2e4b1bc7187b93029e99e590a4e92ff9c39031319766b7fbcdabab9c3dc20b3d27d05eee198cbc717b9aedfbef92bd3e519c62c60e4731bd936a",
|
||
expiresAtTimestamp: 1779507008169,
|
||
},
|
||
],
|
||
};
|
||
|
||
describe("resolveCommitReferences", () => {
|
||
it("flattens commits and enriches items with template metadata", () => {
|
||
const resolved = resolveCommitReferences(
|
||
originalInvitation,
|
||
vendingMachineTemplate,
|
||
);
|
||
|
||
expect(resolved).toEqual({
|
||
invitationIdentifier: "c57b1f8f8534df28b359e323c5fbd5ba",
|
||
templateIdentifier:
|
||
"feadd05c6566c5eded68f321efe7150cb765fda070d027c89f285e5b42a00652",
|
||
actionIdentifier: "purchaseItems",
|
||
variables: [
|
||
{
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
name: "Total Price",
|
||
description: "Total purchase price in satoshis",
|
||
type: "integer",
|
||
hint: "satoshis",
|
||
variableIdentifier: "totalSatoshis",
|
||
roleIdentifier: "merchant",
|
||
value: 3000,
|
||
},
|
||
{
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
name: "Order ID",
|
||
description: "Unique order identifier",
|
||
type: "string",
|
||
variableIdentifier: "orderId",
|
||
roleIdentifier: "merchant",
|
||
value: "eb5a30b3-ec8c-4b81-89dd-c53371f55a0e",
|
||
},
|
||
{
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
name: "Merchant Name",
|
||
description: "Display name of the vending machine",
|
||
type: "string",
|
||
variableIdentifier: "merchantName",
|
||
roleIdentifier: "merchant",
|
||
value: "XO Snack Machine",
|
||
},
|
||
{
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
name: "Receipt Summary",
|
||
description: "Human-readable list of purchased items",
|
||
type: "string",
|
||
variableIdentifier: "receiptSummary",
|
||
roleIdentifier: "merchant",
|
||
value: "2× Chips",
|
||
},
|
||
{
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
name: "Line Items",
|
||
description: "JSON-encoded line items for the purchase",
|
||
type: "string",
|
||
variableIdentifier: "lineItemsJson",
|
||
roleIdentifier: "merchant",
|
||
value:
|
||
'[{"id":"225e37f4-14f2-4b33-86fd-763018bbfd7c","name":"Chips","quantity":2,"price":1500}]',
|
||
},
|
||
],
|
||
inputs: [
|
||
{
|
||
entityIdentifier: CUSTOMER_ENTITY,
|
||
outpointTransactionHash:
|
||
"b1e8f77cdc60efac19f668fc5c7177ace42a46e2532f230979559c7190c3c80a",
|
||
outpointIndex: 1,
|
||
},
|
||
],
|
||
outputs: [
|
||
{
|
||
entityIdentifier: MERCHANT_ENTITY,
|
||
outputIdentifier: "purchaseOutput",
|
||
lockingBytecode:
|
||
"76a9146a4715fe1cc1ce228336502f1711b06045ef361088ac",
|
||
name: "Purchase Payment",
|
||
description: "$(<totalSatoshis>) sats to $(<merchantName>)",
|
||
icon: "request",
|
||
roles: {
|
||
merchant: {
|
||
name: "Payment Received",
|
||
description:
|
||
"Received $(<totalSatoshis>) sats for $(<receiptSummary>)",
|
||
},
|
||
customer: {
|
||
name: "Payment Sent",
|
||
description:
|
||
"Sent $(<totalSatoshis>) sats for $(<receiptSummary>)",
|
||
},
|
||
},
|
||
lockingScript: "merchantReceivingLockingScript",
|
||
valueSatoshis: "$(<totalSatoshis>)",
|
||
token: null,
|
||
},
|
||
{
|
||
entityIdentifier: CUSTOMER_ENTITY,
|
||
valueSatoshis: 74881n,
|
||
lockingBytecode:
|
||
"76a9141730ca066d4b9c8d542f8c9bdce645f77697d46088ac",
|
||
},
|
||
],
|
||
});
|
||
});
|
||
|
||
it("leaves unidentified inputs and outputs without template metadata", () => {
|
||
const resolved = resolveCommitReferences(
|
||
originalInvitation,
|
||
vendingMachineTemplate,
|
||
);
|
||
|
||
expect(resolved.inputs[0]).not.toHaveProperty("name");
|
||
expect(resolved.outputs[1]).not.toHaveProperty("name");
|
||
expect(resolved.outputs[1]).not.toHaveProperty("outputIdentifier");
|
||
});
|
||
});
|