@totemsdk/edge-adapters 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/artifact-cache.d.ts +36 -0
  2. package/dist/artifact-cache.js +79 -0
  3. package/dist/cjs/artifact-cache.d.ts +36 -0
  4. package/dist/cjs/artifact-cache.js +82 -0
  5. package/dist/cjs/identity.d.ts +19 -0
  6. package/dist/cjs/identity.js +61 -0
  7. package/dist/cjs/index.d.ts +25 -0
  8. package/dist/cjs/index.js +41 -0
  9. package/dist/cjs/liquidity.d.ts +15 -0
  10. package/dist/cjs/liquidity.js +45 -0
  11. package/dist/cjs/location.d.ts +48 -0
  12. package/dist/cjs/location.js +208 -0
  13. package/dist/cjs/lookup.d.ts +13 -0
  14. package/dist/cjs/lookup.js +96 -0
  15. package/dist/cjs/manifest.d.ts +11 -0
  16. package/dist/cjs/manifest.js +36 -0
  17. package/dist/cjs/negotiation-transport.d.ts +50 -0
  18. package/dist/cjs/negotiation-transport.js +122 -0
  19. package/dist/cjs/omnia.d.ts +7 -0
  20. package/dist/cjs/omnia.js +46 -0
  21. package/dist/cjs/package.json +1 -0
  22. package/dist/cjs/payment-l1.d.ts +38 -0
  23. package/dist/cjs/payment-l1.js +46 -0
  24. package/dist/cjs/payment-l2.d.ts +39 -0
  25. package/dist/cjs/payment-l2.js +54 -0
  26. package/dist/cjs/policy.d.ts +13 -0
  27. package/dist/cjs/policy.js +95 -0
  28. package/dist/cjs/proof.d.ts +48 -0
  29. package/dist/cjs/proof.js +88 -0
  30. package/dist/cjs/pubsub.d.ts +11 -0
  31. package/dist/cjs/pubsub.js +30 -0
  32. package/dist/cjs/purchase-authority.d.ts +42 -0
  33. package/dist/cjs/purchase-authority.js +79 -0
  34. package/dist/cjs/purchase-lookup.d.ts +44 -0
  35. package/dist/cjs/purchase-lookup.js +60 -0
  36. package/dist/cjs/purchase-payment.d.ts +78 -0
  37. package/dist/cjs/purchase-payment.js +108 -0
  38. package/dist/cjs/sqlite-commerce-store.d.ts +69 -0
  39. package/dist/cjs/sqlite-commerce-store.js +416 -0
  40. package/dist/cjs/stream.d.ts +7 -0
  41. package/dist/cjs/stream.js +26 -0
  42. package/dist/identity.js +4 -7
  43. package/dist/index.d.ts +6 -0
  44. package/dist/index.js +18 -27
  45. package/dist/liquidity.js +1 -4
  46. package/dist/location.js +10 -13
  47. package/dist/lookup.js +3 -6
  48. package/dist/manifest.js +5 -7
  49. package/dist/negotiation-transport.d.ts +50 -0
  50. package/dist/negotiation-transport.js +118 -0
  51. package/dist/omnia.js +1 -4
  52. package/dist/payment-l1.js +1 -4
  53. package/dist/payment-l2.js +5 -8
  54. package/dist/policy.js +1 -4
  55. package/dist/proof.js +7 -10
  56. package/dist/pubsub.js +1 -4
  57. package/dist/purchase-authority.d.ts +42 -0
  58. package/dist/purchase-authority.js +76 -0
  59. package/dist/purchase-lookup.d.ts +44 -0
  60. package/dist/purchase-lookup.js +57 -0
  61. package/dist/purchase-payment.d.ts +78 -0
  62. package/dist/purchase-payment.js +105 -0
  63. package/dist/sqlite-commerce-store.d.ts +69 -0
  64. package/dist/sqlite-commerce-store.js +411 -0
  65. package/dist/stream.js +1 -4
  66. package/package.json +37 -26
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMinimaL1PaymentPort = createMinimaL1PaymentPort;
4
+ /**
5
+ * Minima L1 payment adapter.
6
+ *
7
+ * Delegates transaction construction and signing to the injected `sign` function,
8
+ * then broadcasts the result via the ChainStateProvider. This keeps key material
9
+ * out of the adapter entirely.
10
+ *
11
+ * For a batteries-included L1 adapter backed by @totemsdk/server's sendTransaction,
12
+ * wrap sendTransaction in the sign callback:
13
+ *
14
+ * createMinimaL1PaymentPort({
15
+ * provider: new PureMinimaRpcProvider(rpcConfig),
16
+ * sign: ({ toAddress, amount, tokenId }) =>
17
+ * sendTransaction({ seed, addressIndex, toAddress, amount, tokenId, ... })
18
+ * .then(r => r.minedHex),
19
+ * })
20
+ */
21
+ function createMinimaL1PaymentPort(config) {
22
+ return {
23
+ async pay(params) {
24
+ try {
25
+ const txpowHex = await config.sign({
26
+ toAddress: params.recipient,
27
+ amount: params.amount,
28
+ tokenId: params.tokenId ?? '0x00',
29
+ memo: params.memo,
30
+ });
31
+ const result = await config.provider.broadcastTxPoW(txpowHex);
32
+ if (!result.success) {
33
+ return {
34
+ ok: false,
35
+ error: result.message ?? 'Broadcast failed',
36
+ errorCode: 'BROADCAST_FAILED',
37
+ };
38
+ }
39
+ return { ok: true, data: { txpowId: result.txpowid } };
40
+ }
41
+ catch (err) {
42
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
43
+ }
44
+ },
45
+ };
46
+ }
@@ -0,0 +1,39 @@
1
+ import type { ChannelGraph, ChannelOps, RouterChannel, LeaseProvider, RouteOptions } from '@totemsdk/omnia-router';
2
+ import type { EdgePaymentPort } from '@totemsdk/edge';
3
+ export interface OmniaL2PaymentPortConfig {
4
+ /** Routing graph (edges + swap index). Updated externally as channels open/close. */
5
+ graph: ChannelGraph;
6
+ /**
7
+ * Live channel state keyed by channelId.
8
+ * executeMultiHopPayment mutates this map in-place as HTLCs are added/settled.
9
+ * Callers are responsible for keeping it in sync with the on-chain state.
10
+ */
11
+ channels: Map<string, RouterChannel>;
12
+ /** HTLC operations (addHTLC, fulfillHTLC, timeoutHTLC) for each channel. */
13
+ ops: ChannelOps;
14
+ /** WOTS lease providers keyed by channelId — required for HTLC signing. */
15
+ leaseProviders: Map<string, LeaseProvider>;
16
+ /** Public key digest identifying the local party in each channel. */
17
+ localPublicKeyDigest: string;
18
+ /**
19
+ * Returns the current chain block height. Used to compute HTLC expiry.
20
+ * Typically: `async () => BigInt((await provider.getTip()).block)`.
21
+ */
22
+ getCurrentBlock(): Promise<bigint>;
23
+ /** HTLC timeout in blocks past the current tip. Defaults to 144 (≈24h on Minima). */
24
+ htlcTimeoutBlocks?: bigint;
25
+ /** Optional pathfinding overrides forwarded to findRoute. */
26
+ routeOptions?: RouteOptions;
27
+ }
28
+ /**
29
+ * Omnia L2 payment adapter.
30
+ *
31
+ * Routes payments over Omnia payment channels using multi-hop HTLC execution.
32
+ * The local node must already have open channels forming a path to the recipient.
33
+ *
34
+ * pay() finds a route, builds a PaymentRequest, and executes atomically:
35
+ * 1. Forward phase — locks HTLCs across each hop.
36
+ * 2. Reveal phase — reveals the preimage in reverse to settle all hops.
37
+ * Rollback (best-effort timeoutHTLC) fires on any failure.
38
+ */
39
+ export declare function createOmniaL2PaymentPort(config: OmniaL2PaymentPortConfig): EdgePaymentPort;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createOmniaL2PaymentPort = createOmniaL2PaymentPort;
4
+ const omnia_router_1 = require("@totemsdk/omnia-router");
5
+ const _SCALE = 100000000n;
6
+ function _toScaled(s) {
7
+ const [i, f = ''] = s.split('.');
8
+ return BigInt(i || '0') * _SCALE + BigInt(f.padEnd(8, '0').slice(0, 8));
9
+ }
10
+ /**
11
+ * Omnia L2 payment adapter.
12
+ *
13
+ * Routes payments over Omnia payment channels using multi-hop HTLC execution.
14
+ * The local node must already have open channels forming a path to the recipient.
15
+ *
16
+ * pay() finds a route, builds a PaymentRequest, and executes atomically:
17
+ * 1. Forward phase — locks HTLCs across each hop.
18
+ * 2. Reveal phase — reveals the preimage in reverse to settle all hops.
19
+ * Rollback (best-effort timeoutHTLC) fires on any failure.
20
+ */
21
+ function createOmniaL2PaymentPort(config) {
22
+ const htlcTimeoutBlocks = config.htlcTimeoutBlocks ?? 144n;
23
+ return {
24
+ async pay(params) {
25
+ try {
26
+ const tokenId = params.tokenId ?? '0x00';
27
+ const amount = _toScaled(params.amount);
28
+ const route = (0, omnia_router_1.findRoute)(config.graph, config.localPublicKeyDigest, params.recipient, amount, tokenId, config.routeOptions);
29
+ if (!route) {
30
+ return {
31
+ ok: false,
32
+ error: `No route found to ${params.recipient} for amount ${params.amount} (${tokenId})`,
33
+ errorCode: 'NO_ROUTE',
34
+ };
35
+ }
36
+ const currentBlock = await config.getCurrentBlock();
37
+ const expiryBlock = currentBlock + htlcTimeoutBlocks;
38
+ const request = (0, omnia_router_1.buildPaymentRequest)(amount, tokenId, expiryBlock);
39
+ const result = await (0, omnia_router_1.executeMultiHopPayment)(config.ops, config.channels, route, request, config.leaseProviders);
40
+ if (!result.success) {
41
+ return {
42
+ ok: false,
43
+ error: result.error ?? 'Multi-hop payment failed',
44
+ errorCode: 'PAYMENT_FAILED',
45
+ };
46
+ }
47
+ return { ok: true, data: { txpowId: result.preimage } };
48
+ }
49
+ catch (err) {
50
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
51
+ }
52
+ },
53
+ };
54
+ }
@@ -0,0 +1,13 @@
1
+ import type { AgentPolicy, PolicyMiddleware } from '@totemsdk/agent-policy';
2
+ import type { EdgePolicyPort } from '@totemsdk/edge';
3
+ type PolicyLike = AgentPolicy | PolicyMiddleware;
4
+ /**
5
+ * Wraps an AgentPolicy or PolicyMiddleware as an EdgePolicyPort.
6
+ *
7
+ * When the EdgePolicyPort receives a full `proposal` object, it delegates
8
+ * directly to the policy without lossy reconstruction. When only flat
9
+ * `action`/`subject` params are provided, it builds a minimal AgentProposal
10
+ * (legacy path).
11
+ */
12
+ export declare function createPolicyPortAdapter(policy: PolicyLike): EdgePolicyPort;
13
+ export {};
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPolicyPortAdapter = createPolicyPortAdapter;
4
+ function isMiddleware(p) {
5
+ return 'evaluate' in p && typeof p.evaluate === 'function';
6
+ }
7
+ /**
8
+ * Wraps an AgentPolicy or PolicyMiddleware as an EdgePolicyPort.
9
+ *
10
+ * When the EdgePolicyPort receives a full `proposal` object, it delegates
11
+ * directly to the policy without lossy reconstruction. When only flat
12
+ * `action`/`subject` params are provided, it builds a minimal AgentProposal
13
+ * (legacy path).
14
+ */
15
+ function createPolicyPortAdapter(policy) {
16
+ return {
17
+ async check(params) {
18
+ try {
19
+ // Prefer full proposal when available
20
+ if (params.proposal) {
21
+ const proposal = {
22
+ id: params.proposal.id,
23
+ agentId: params.proposal.agentId,
24
+ intent: {
25
+ type: params.proposal.intent.type,
26
+ amount: params.proposal.intent.amount,
27
+ tokenId: params.proposal.intent.tokenId,
28
+ recipient: params.proposal.intent.recipient,
29
+ reason: params.proposal.intent.reason,
30
+ risk: params.proposal.intent.risk,
31
+ },
32
+ explanation: params.proposal.explanation,
33
+ confidence: params.proposal.confidence,
34
+ createdAt: params.proposal.createdAt,
35
+ };
36
+ if (isMiddleware(policy)) {
37
+ const result = await policy.evaluate(proposal);
38
+ return {
39
+ ok: true,
40
+ data: {
41
+ allowed: result.outcome === 'approved',
42
+ reason: result.reason,
43
+ },
44
+ };
45
+ }
46
+ const allowed = await policy.canAutoApprove(proposal);
47
+ return {
48
+ ok: true,
49
+ data: {
50
+ allowed,
51
+ reason: allowed ? undefined : 'Action requires user approval per configured policy',
52
+ },
53
+ };
54
+ }
55
+ // Legacy path: build minimal proposal from flat params
56
+ const intentType = params.action.startsWith('pay') ? 'payment' : 'receipt';
57
+ const proposal = {
58
+ id: `edge-policy-${params.action}-${params.subject}-${Date.now()}`,
59
+ agentId: 'edge-policy-adapter',
60
+ intent: {
61
+ type: intentType,
62
+ recipient: params.subject,
63
+ reason: params.action,
64
+ risk: params.context?.['risk'] ?? 'low',
65
+ metadata: params.context,
66
+ },
67
+ explanation: `Policy check for action "${params.action}" by subject "${params.subject}"`,
68
+ confidence: 1,
69
+ createdAt: Date.now(),
70
+ };
71
+ if (isMiddleware(policy)) {
72
+ const result = await policy.evaluate(proposal);
73
+ return {
74
+ ok: true,
75
+ data: {
76
+ allowed: result.outcome === 'approved',
77
+ reason: result.reason,
78
+ },
79
+ };
80
+ }
81
+ const allowed = await policy.canAutoApprove(proposal);
82
+ return {
83
+ ok: true,
84
+ data: {
85
+ allowed,
86
+ reason: allowed ? undefined : 'Action requires user approval per configured policy',
87
+ },
88
+ };
89
+ }
90
+ catch (err) {
91
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
92
+ }
93
+ },
94
+ };
95
+ }
@@ -0,0 +1,48 @@
1
+ import type { ProofProvider, ProofKind } from '@totemsdk/proof';
2
+ import type { EdgeProofPort } from '@totemsdk/edge';
3
+ export interface ProofPortConfig {
4
+ provider: ProofProvider;
5
+ /** Issuer address or identifier stamped onto created proofs. */
6
+ issuer: string;
7
+ /** Default proof kind when callers don't specify one via context. */
8
+ defaultKind?: ProofKind;
9
+ /**
10
+ * 32-byte WOTS seed. Required for signing; without it only unsigned
11
+ * proofs are returned, which MUST NOT be presented as completed proofs.
12
+ */
13
+ seed?: Uint8Array;
14
+ /**
15
+ * TreeKey index for direct signing (used when no leaseProvider is given).
16
+ * Ignored when leaseProvider is set.
17
+ */
18
+ keyIndex?: number;
19
+ /**
20
+ * WOTS lease provider for coordinated key-index reservation.
21
+ * When set, keyIndex is ignored and the index is reserved via the provider.
22
+ */
23
+ leaseProvider?: {
24
+ reserveKeyUse(params: {
25
+ treeId: string;
26
+ ttlMs?: number;
27
+ payloadHash?: string;
28
+ }): Promise<{
29
+ reservationId: string;
30
+ indices: {
31
+ addressIndex: number;
32
+ l1: number;
33
+ l2: number;
34
+ };
35
+ }>;
36
+ commitKeyUse(reservationId: string, txId: string): Promise<void>;
37
+ burnReservation(reservationId: string, reason: string): Promise<void>;
38
+ };
39
+ leaseTreeId?: string;
40
+ }
41
+ /**
42
+ * Wraps a ProofProvider (e.g. proof-integritas) as an EdgeProofPort.
43
+ *
44
+ * When config.seed is provided the returned proof is a SignedProof;
45
+ * without seed only an UnsignedProof is returned and MUST NOT be
46
+ * presented as a completed proof.
47
+ */
48
+ export declare function createProofPortAdapter(config: ProofPortConfig): EdgeProofPort;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createProofPortAdapter = createProofPortAdapter;
4
+ const proof_1 = require("@totemsdk/proof");
5
+ function rawPayloadEvidence(rawPayload) {
6
+ if (!rawPayload || rawPayload.length === 0)
7
+ return undefined;
8
+ const hash = (0, proof_1.toHex)((0, proof_1.sha3_256)(rawPayload));
9
+ return { id: 'payload:' + hash, kind: 'raw-payload', hash };
10
+ }
11
+ /**
12
+ * Wraps a ProofProvider (e.g. proof-integritas) as an EdgeProofPort.
13
+ *
14
+ * When config.seed is provided the returned proof is a SignedProof;
15
+ * without seed only an UnsignedProof is returned and MUST NOT be
16
+ * presented as a completed proof.
17
+ */
18
+ function createProofPortAdapter(config) {
19
+ const { provider, issuer, defaultKind = 'attestation' } = config;
20
+ return {
21
+ async createProof(params) {
22
+ try {
23
+ const kind = params.context?.['kind'] ?? defaultKind;
24
+ const rawPayload = params.context?.['rawPayload'];
25
+ const evidence = rawPayloadEvidence(rawPayload);
26
+ const unsigned = (0, proof_1.createProof)({
27
+ kind,
28
+ subject: { id: params.subject, kind: 'edge-subject' },
29
+ issuer,
30
+ payload: {
31
+ claims: params.claims,
32
+ ...(rawPayload !== undefined ? { rawPayloadHash: (0, proof_1.toHex)((0, proof_1.sha3_256)(rawPayload)) } : {}),
33
+ ...(params.context ?? {}),
34
+ },
35
+ ...(evidence !== undefined ? { evidence: [evidence] } : {}),
36
+ });
37
+ // Sign if seed is available
38
+ let proof;
39
+ let proofId;
40
+ if (config.seed) {
41
+ if (config.leaseProvider) {
42
+ proof = await (0, proof_1.signWithLease)(unsigned, config.seed, config.leaseProvider, {
43
+ treeId: config.leaseTreeId,
44
+ });
45
+ }
46
+ else {
47
+ proof = (0, proof_1.signProof)(unsigned, config.seed, config.keyIndex ?? 0);
48
+ }
49
+ proofId = proof.proofId;
50
+ }
51
+ else {
52
+ proof = unsigned;
53
+ proofId = unsigned.proofId;
54
+ }
55
+ // Stamp the proof's canonical hash if the provider supports it.
56
+ if (provider.stampHash) {
57
+ await provider.stampHash({ hash: proofId });
58
+ }
59
+ return { ok: true, data: { proofId, proof } };
60
+ }
61
+ catch (err) {
62
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
63
+ }
64
+ },
65
+ async verifyProof(params) {
66
+ try {
67
+ const proof = params.proof;
68
+ if (provider.verifyProof) {
69
+ const result = await provider.verifyProof(proof);
70
+ return { ok: true, data: { valid: result.valid, reason: result.reason } };
71
+ }
72
+ if (provider.checkProof) {
73
+ const result = await provider.checkProof(proof);
74
+ const valid = result.ok && !result.error;
75
+ return { ok: true, data: { valid, reason: result.error } };
76
+ }
77
+ return {
78
+ ok: false,
79
+ error: 'Provider does not support proof verification',
80
+ errorCode: 'NO_VERIFY_CAPABILITY',
81
+ };
82
+ }
83
+ catch (err) {
84
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
85
+ }
86
+ },
87
+ };
88
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * EdgePubSubPort adapter — wraps @totemsdk/pubsub-transport's IPubSubTransport
3
+ * as a first-class EdgePubSubPort for EdgeRuntimePorts.pubsub.
4
+ *
5
+ * This is the lightweight counterpart to @totemsdk/edge-mqtt — it provides
6
+ * the raw pub/sub port without the rule engine, sensor bridge, proof
7
+ * publisher, command handler, or MachinePay credit enforcement.
8
+ */
9
+ import type { EdgePubSubPort } from '@totemsdk/edge';
10
+ import type { IPubSubTransport } from '@totemsdk/pubsub-transport';
11
+ export declare function createPubSubPortAdapter(transport: IPubSubTransport): EdgePubSubPort;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * EdgePubSubPort adapter — wraps @totemsdk/pubsub-transport's IPubSubTransport
4
+ * as a first-class EdgePubSubPort for EdgeRuntimePorts.pubsub.
5
+ *
6
+ * This is the lightweight counterpart to @totemsdk/edge-mqtt — it provides
7
+ * the raw pub/sub port without the rule engine, sensor bridge, proof
8
+ * publisher, command handler, or MachinePay credit enforcement.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.createPubSubPortAdapter = createPubSubPortAdapter;
12
+ function createPubSubPortAdapter(transport) {
13
+ return {
14
+ async connect() {
15
+ await transport.connect();
16
+ },
17
+ async disconnect() {
18
+ await transport.disconnect();
19
+ },
20
+ async subscribe(topic) {
21
+ return transport.subscribe(topic);
22
+ },
23
+ async publish(topic, payload) {
24
+ await transport.publish(topic, payload);
25
+ },
26
+ onMessage(handler) {
27
+ return transport.onMessage(handler);
28
+ },
29
+ };
30
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * purchase-authority.ts — AuthorityPort adapter over @totemsdk/agent-policy.
3
+ *
4
+ * Maps a machine-commerce TradeAgreement + PurchaseIntent to an AgentProposal
5
+ * and evaluates it through a ComposablePolicy (or any AgentPolicy).
6
+ *
7
+ * Architectural boundary preserved:
8
+ * TradeProposal = machine ↔ machine bargaining (peer-to-peer)
9
+ * AgentProposal = agent → trusted local authority (wallet/policy)
10
+ *
11
+ * The machine negotiation strategy never receives a private key. This adapter
12
+ * is the trusted boundary that decides whether the local authority approves
13
+ * the economic commitment.
14
+ */
15
+ import type { AgentPolicy, PolicyMiddleware } from '@totemsdk/agent-policy';
16
+ import type { EdgeOperationResult } from '@totemsdk/edge';
17
+ import type { PurchaseIntent, TradeAgreement } from '@totemsdk/edge';
18
+ type PolicyLike = AgentPolicy | PolicyMiddleware;
19
+ export interface PurchaseAuthorityAdapterConfig {
20
+ /** The local policy (ComposablePolicy, AgentPolicy, or PolicyMiddleware). */
21
+ policy: PolicyLike;
22
+ /** Agent identifier used in the AgentProposal (e.g. 'edge-purchase-agent'). */
23
+ agentId?: string;
24
+ /** Optional risk level for the proposal. */
25
+ risk?: 'low' | 'medium' | 'high';
26
+ }
27
+ /**
28
+ * Create an AuthorityPort adapter over an agent-policy.
29
+ *
30
+ * approve() builds an AgentProposal from the agreement + intent and evaluates
31
+ * it through the policy. Returns `{ allowed, reason }`.
32
+ */
33
+ export declare function createPurchaseAuthorityAdapter(config: PurchaseAuthorityAdapterConfig): {
34
+ approve(params: {
35
+ agreement: TradeAgreement;
36
+ intent: PurchaseIntent;
37
+ }): Promise<EdgeOperationResult<{
38
+ allowed: boolean;
39
+ reason?: string;
40
+ }>>;
41
+ };
42
+ export {};
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ /**
3
+ * purchase-authority.ts — AuthorityPort adapter over @totemsdk/agent-policy.
4
+ *
5
+ * Maps a machine-commerce TradeAgreement + PurchaseIntent to an AgentProposal
6
+ * and evaluates it through a ComposablePolicy (or any AgentPolicy).
7
+ *
8
+ * Architectural boundary preserved:
9
+ * TradeProposal = machine ↔ machine bargaining (peer-to-peer)
10
+ * AgentProposal = agent → trusted local authority (wallet/policy)
11
+ *
12
+ * The machine negotiation strategy never receives a private key. This adapter
13
+ * is the trusted boundary that decides whether the local authority approves
14
+ * the economic commitment.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.createPurchaseAuthorityAdapter = createPurchaseAuthorityAdapter;
18
+ function isMiddleware(p) {
19
+ return 'evaluate' in p && typeof p.evaluate === 'function';
20
+ }
21
+ /**
22
+ * Create an AuthorityPort adapter over an agent-policy.
23
+ *
24
+ * approve() builds an AgentProposal from the agreement + intent and evaluates
25
+ * it through the policy. Returns `{ allowed, reason }`.
26
+ */
27
+ function createPurchaseAuthorityAdapter(config) {
28
+ const { policy } = config;
29
+ const agentId = config.agentId ?? 'edge-purchase-agent';
30
+ const risk = config.risk ?? 'medium';
31
+ return {
32
+ async approve(params) {
33
+ try {
34
+ const { agreement, intent } = params;
35
+ const proposal = {
36
+ id: `edge-purchase:${agreement.agreementId}`,
37
+ agentId,
38
+ intent: {
39
+ type: 'payment',
40
+ amount: agreement.terms.price,
41
+ tokenId: agreement.terms.tokenId,
42
+ recipient: agreement.seller,
43
+ reason: `purchase ${intent.resource} from ${agreement.seller}`,
44
+ risk,
45
+ metadata: {
46
+ agreementId: agreement.agreementId,
47
+ negotiationId: agreement.negotiationId,
48
+ resource: intent.resource,
49
+ },
50
+ },
51
+ explanation: `Machine purchase of ${intent.resource} for ${agreement.terms.price} ${agreement.terms.tokenId ?? '0x00'} from ${agreement.seller}`,
52
+ confidence: 1,
53
+ createdAt: Date.now(),
54
+ };
55
+ if (isMiddleware(policy)) {
56
+ const result = await policy.evaluate(proposal);
57
+ return {
58
+ ok: true,
59
+ data: {
60
+ allowed: result.outcome === 'approved',
61
+ reason: result.reason,
62
+ },
63
+ };
64
+ }
65
+ const allowed = await policy.canAutoApprove(proposal);
66
+ return {
67
+ ok: true,
68
+ data: {
69
+ allowed,
70
+ reason: allowed ? undefined : 'Purchase requires user approval per configured policy',
71
+ },
72
+ };
73
+ }
74
+ catch (err) {
75
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
76
+ }
77
+ },
78
+ };
79
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * purchase-lookup.ts — PurchaseLookupPort adapter over @totemsdk/lookup-client.
3
+ *
4
+ * Maps a machine-commerce `resource` (e.g. "compute", "storage") to a
5
+ * capability query on the Lookup Node, returning signed manifests for the
6
+ * buyer's discovery flow.
7
+ *
8
+ * Discovery is publication, not authority: the buyer MUST still verify each
9
+ * returned manifest's signature, identity binding, expiry, and capabilities
10
+ * before negotiation/payment. This adapter only fetches candidates.
11
+ */
12
+ import type { LookupClient } from '@totemsdk/lookup-client';
13
+ import type { EdgeOperationResult } from '@totemsdk/edge';
14
+ export interface PurchaseLookupAdapterConfig {
15
+ client: LookupClient;
16
+ /** Optional provider address filter (authorAddress for apps). */
17
+ provider?: string;
18
+ /** Optional max price filter (agents). */
19
+ maxPricePerCall?: number;
20
+ /** Optional max latency filter (agents). */
21
+ maxLatencyMs?: number;
22
+ /** Optional result limit. */
23
+ limit?: number;
24
+ }
25
+ /**
26
+ * Create a PurchaseLookupPort adapter over a LookupClient.
27
+ *
28
+ * `resource` is treated as a capability name for agent manifests (the
29
+ * machine-commerce case). If the resource matches a known app category, it
30
+ * falls back to app queries. Returns `{ id, manifest: Uint8Array, nodeId }`
31
+ * candidates for the buyer's manifest-verification pipeline.
32
+ */
33
+ export declare function createPurchaseLookupAdapter(config: PurchaseLookupAdapterConfig): {
34
+ query(params: {
35
+ resource: string;
36
+ provider?: string;
37
+ }): Promise<EdgeOperationResult<{
38
+ results: Array<{
39
+ id: string;
40
+ manifest: Uint8Array;
41
+ nodeId: string;
42
+ }>;
43
+ }>>;
44
+ };
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /**
3
+ * purchase-lookup.ts — PurchaseLookupPort adapter over @totemsdk/lookup-client.
4
+ *
5
+ * Maps a machine-commerce `resource` (e.g. "compute", "storage") to a
6
+ * capability query on the Lookup Node, returning signed manifests for the
7
+ * buyer's discovery flow.
8
+ *
9
+ * Discovery is publication, not authority: the buyer MUST still verify each
10
+ * returned manifest's signature, identity binding, expiry, and capabilities
11
+ * before negotiation/payment. This adapter only fetches candidates.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.createPurchaseLookupAdapter = createPurchaseLookupAdapter;
15
+ /**
16
+ * Create a PurchaseLookupPort adapter over a LookupClient.
17
+ *
18
+ * `resource` is treated as a capability name for agent manifests (the
19
+ * machine-commerce case). If the resource matches a known app category, it
20
+ * falls back to app queries. Returns `{ id, manifest: Uint8Array, nodeId }`
21
+ * candidates for the buyer's manifest-verification pipeline.
22
+ */
23
+ function createPurchaseLookupAdapter(config) {
24
+ const { client } = config;
25
+ return {
26
+ async query(params) {
27
+ try {
28
+ const provider = params.provider ?? config.provider;
29
+ const limit = config.limit ?? 20;
30
+ // Agent capability query (machine-commerce primary path).
31
+ const agents = await client.queryAgents({
32
+ capabilityName: params.resource,
33
+ maxPricePerCall: config.maxPricePerCall,
34
+ maxLatencyMs: config.maxLatencyMs,
35
+ limit,
36
+ });
37
+ const results = agents.map((a) => ({
38
+ id: a.capabilityId,
39
+ manifest: a.manifest,
40
+ nodeId: a.nodeId,
41
+ }));
42
+ // If no agent results and a provider is specified, also try app query
43
+ // filtered by author address (provider = operator).
44
+ if (results.length === 0 && provider) {
45
+ const apps = await client.queryApps({
46
+ authorAddress: provider,
47
+ limit,
48
+ });
49
+ for (const a of apps) {
50
+ results.push({ id: a.appId, manifest: a.manifest, nodeId: a.nodeId });
51
+ }
52
+ }
53
+ return { ok: true, data: { results } };
54
+ }
55
+ catch (err) {
56
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
57
+ }
58
+ },
59
+ };
60
+ }