@totemsdk/edge 0.1.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.
- package/README.md +24 -0
- package/dist/canonical.d.ts +13 -0
- package/dist/canonical.js +28 -0
- package/dist/capabilities.d.ts +21 -0
- package/dist/capabilities.js +85 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/device.d.ts +10 -0
- package/dist/device.js +20 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +11 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +14 -0
- package/dist/ports.d.ts +94 -0
- package/dist/ports.js +7 -0
- package/dist/provider.d.ts +27 -0
- package/dist/provider.js +48 -0
- package/dist/receipts.d.ts +20 -0
- package/dist/receipts.js +45 -0
- package/dist/runtime.d.ts +11 -0
- package/dist/runtime.js +20 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +7 -0
- package/package.json +58 -0
- package/src/__tests__/edge.test.ts +370 -0
- package/src/canonical.ts +29 -0
- package/src/capabilities.ts +115 -0
- package/src/constants.ts +1 -0
- package/src/device.ts +30 -0
- package/src/errors.ts +15 -0
- package/src/index.ts +52 -0
- package/src/ports.ts +75 -0
- package/src/provider.ts +77 -0
- package/src/receipts.ts +60 -0
- package/src/runtime.ts +33 -0
- package/src/types.ts +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @totemsdk/edge
|
|
2
|
+
|
|
3
|
+
Unified developer-facing runtime for Totem Edge.
|
|
4
|
+
|
|
5
|
+
## Design
|
|
6
|
+
|
|
7
|
+
`@totemsdk/edge` composes identity, manifest, wallet/payment/proof/lookup/policy capabilities
|
|
8
|
+
via injected port interfaces. It is adapter-neutral — no ROS2, no MQTT, no Python bindings,
|
|
9
|
+
no direct proof implementation.
|
|
10
|
+
|
|
11
|
+
## `@totemsdk/connect` as a peer dependency
|
|
12
|
+
|
|
13
|
+
`edgeCapabilitiesFromTotemCapabilities(caps: TotemCapabilities)` is a public exported
|
|
14
|
+
function. Because `TotemCapabilities` appears in the emitted `.d.ts`, `@totemsdk/connect`
|
|
15
|
+
is declared as both a `peerDependency` and a `devDependency`. It is imported with
|
|
16
|
+
`import type` exclusively — no runtime import is emitted, so `@totemsdk/edge` remains
|
|
17
|
+
independently deployable without `@totemsdk/connect` being installed at runtime.
|
|
18
|
+
|
|
19
|
+
## Port pattern
|
|
20
|
+
|
|
21
|
+
All capability ports (`EdgePaymentPort`, `EdgeLiquidityPort`, `EdgeProofPort`,
|
|
22
|
+
`EdgeLookupPort`, `EdgePolicyPort`, `EdgeIdentityPort`, `EdgeManifestPort`) are
|
|
23
|
+
interfaces only. Callers inject implementations at runtime via `EdgeRuntimePorts`.
|
|
24
|
+
`@totemsdk/edge` ships no proof creation/verification implementations.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain hex encoder (no 0x prefix) for use in ID URIs and deterministic identifiers.
|
|
3
|
+
* bytesToHex from @totemsdk/core adds a 0x prefix — use this for URI-safe hex IDs.
|
|
4
|
+
*/
|
|
5
|
+
export declare function toHex(bytes: Uint8Array): string;
|
|
6
|
+
/**
|
|
7
|
+
* Local canonical JSON helper for @totemsdk/edge.
|
|
8
|
+
*
|
|
9
|
+
* Identical in behaviour to the one in @totemsdk/identity, but kept local
|
|
10
|
+
* so both packages remain independently deployable. If a shared helper is
|
|
11
|
+
* extracted to a low-level package in a future task it can replace both copies.
|
|
12
|
+
*/
|
|
13
|
+
export declare function canonicalJson(value: unknown): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain hex encoder (no 0x prefix) for use in ID URIs and deterministic identifiers.
|
|
3
|
+
* bytesToHex from @totemsdk/core adds a 0x prefix — use this for URI-safe hex IDs.
|
|
4
|
+
*/
|
|
5
|
+
export function toHex(bytes) {
|
|
6
|
+
return Array.from(bytes)
|
|
7
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
8
|
+
.join('');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Local canonical JSON helper for @totemsdk/edge.
|
|
12
|
+
*
|
|
13
|
+
* Identical in behaviour to the one in @totemsdk/identity, but kept local
|
|
14
|
+
* so both packages remain independently deployable. If a shared helper is
|
|
15
|
+
* extracted to a low-level package in a future task it can replace both copies.
|
|
16
|
+
*/
|
|
17
|
+
export function canonicalJson(value) {
|
|
18
|
+
if (value === null || typeof value !== 'object') {
|
|
19
|
+
return JSON.stringify(value);
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(value)) {
|
|
22
|
+
return '[' + value.map(canonicalJson).join(',') + ']';
|
|
23
|
+
}
|
|
24
|
+
const obj = value;
|
|
25
|
+
const keys = Object.keys(obj).sort();
|
|
26
|
+
const pairs = keys.map((k) => `${JSON.stringify(k)}:${canonicalJson(obj[k])}`);
|
|
27
|
+
return '{' + pairs.join(',') + '}';
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge capability model.
|
|
3
|
+
*
|
|
4
|
+
* EdgeCapability strings follow a domain:action pattern.
|
|
5
|
+
* edgeCapabilitiesFromTotemCapabilities maps @totemsdk/connect's TotemCapabilities
|
|
6
|
+
* to an EdgeCapabilitySet without any runtime import of @totemsdk/connect.
|
|
7
|
+
*/
|
|
8
|
+
import type { TotemCapabilities } from '@totemsdk/connect';
|
|
9
|
+
export type EdgeCapability = 'wallet:self-custody' | 'wallet:wots-tree-key' | 'wallet:root-identity' | 'wallet:seed-export' | 'account:multi-address' | 'account:switcher' | 'chain:hosted-provider' | 'chain:pure-rpc' | 'chain:lookup-node' | 'chain:local-proof-verify' | 'chain:pear-runtime' | 'chain:hyperswarm' | 'txpow:local-mining' | 'txpow:progress-events' | 'omnia:channels' | 'omnia:routing' | 'omnia:multi-hop' | 'omnia:cross-token-swap' | 'omnia:factory' | 'omnia:virtual-channels' | 'omnia:splicing' | 'omnia:hyperswarm' | 'statechain:supported' | 'statechain:blind-se' | 'scripting:kissvm' | 'qvac:payment-intents' | 'qvac:explanations' | 'proof:create' | 'proof:verify' | 'lookup:watch' | 'identity:resolve' | 'manifest:sign' | 'manifest:verify' | 'payment:send' | 'policy:check';
|
|
10
|
+
export type EdgeCapabilitySet = Set<EdgeCapability>;
|
|
11
|
+
export declare function createCapabilitySet(caps: EdgeCapability[]): EdgeCapabilitySet;
|
|
12
|
+
export declare function hasCapability(set: EdgeCapabilitySet, cap: EdgeCapability): boolean;
|
|
13
|
+
export declare function assertCapability(set: EdgeCapabilitySet, cap: EdgeCapability): void;
|
|
14
|
+
/**
|
|
15
|
+
* Maps boolean fields from @totemsdk/connect's TotemCapabilities to the
|
|
16
|
+
* appropriate EdgeCapability strings.
|
|
17
|
+
*
|
|
18
|
+
* @totemsdk/connect is imported as a type-only import — no runtime import
|
|
19
|
+
* is emitted, preserving independent deployability of @totemsdk/edge.
|
|
20
|
+
*/
|
|
21
|
+
export declare function edgeCapabilitiesFromTotemCapabilities(caps: TotemCapabilities): EdgeCapabilitySet;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge capability model.
|
|
3
|
+
*
|
|
4
|
+
* EdgeCapability strings follow a domain:action pattern.
|
|
5
|
+
* edgeCapabilitiesFromTotemCapabilities maps @totemsdk/connect's TotemCapabilities
|
|
6
|
+
* to an EdgeCapabilitySet without any runtime import of @totemsdk/connect.
|
|
7
|
+
*/
|
|
8
|
+
import { EdgeCapabilityError } from './errors.js';
|
|
9
|
+
export function createCapabilitySet(caps) {
|
|
10
|
+
return new Set(caps);
|
|
11
|
+
}
|
|
12
|
+
export function hasCapability(set, cap) {
|
|
13
|
+
return set.has(cap);
|
|
14
|
+
}
|
|
15
|
+
export function assertCapability(set, cap) {
|
|
16
|
+
if (!set.has(cap)) {
|
|
17
|
+
throw new EdgeCapabilityError(cap);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Maps boolean fields from @totemsdk/connect's TotemCapabilities to the
|
|
22
|
+
* appropriate EdgeCapability strings.
|
|
23
|
+
*
|
|
24
|
+
* @totemsdk/connect is imported as a type-only import — no runtime import
|
|
25
|
+
* is emitted, preserving independent deployability of @totemsdk/edge.
|
|
26
|
+
*/
|
|
27
|
+
export function edgeCapabilitiesFromTotemCapabilities(caps) {
|
|
28
|
+
const result = [];
|
|
29
|
+
const { wallet, account, chain, txpow, omnia, statechain, scripting, qvac } = caps;
|
|
30
|
+
if (wallet.selfCustody)
|
|
31
|
+
result.push('wallet:self-custody');
|
|
32
|
+
if (wallet.wotsTreeKey)
|
|
33
|
+
result.push('wallet:wots-tree-key');
|
|
34
|
+
if (wallet.rootIdentity)
|
|
35
|
+
result.push('wallet:root-identity');
|
|
36
|
+
if (wallet.seedExport)
|
|
37
|
+
result.push('wallet:seed-export');
|
|
38
|
+
if (account.multiAddress)
|
|
39
|
+
result.push('account:multi-address');
|
|
40
|
+
if (account.accountSwitcher)
|
|
41
|
+
result.push('account:switcher');
|
|
42
|
+
if (chain.hostedProvider)
|
|
43
|
+
result.push('chain:hosted-provider');
|
|
44
|
+
if (chain.pureMinimaRpc)
|
|
45
|
+
result.push('chain:pure-rpc');
|
|
46
|
+
if (chain.lookupNode)
|
|
47
|
+
result.push('chain:lookup-node');
|
|
48
|
+
if (chain.localProofVerify)
|
|
49
|
+
result.push('chain:local-proof-verify');
|
|
50
|
+
if (chain.pearRuntime)
|
|
51
|
+
result.push('chain:pear-runtime');
|
|
52
|
+
if (chain.hyperswarm)
|
|
53
|
+
result.push('chain:hyperswarm');
|
|
54
|
+
if (txpow.localMining)
|
|
55
|
+
result.push('txpow:local-mining');
|
|
56
|
+
if (txpow.progressEvents)
|
|
57
|
+
result.push('txpow:progress-events');
|
|
58
|
+
if (omnia.channels)
|
|
59
|
+
result.push('omnia:channels');
|
|
60
|
+
if (omnia.routing)
|
|
61
|
+
result.push('omnia:routing');
|
|
62
|
+
if (omnia.multiHop)
|
|
63
|
+
result.push('omnia:multi-hop');
|
|
64
|
+
if (omnia.crossTokenSwap)
|
|
65
|
+
result.push('omnia:cross-token-swap');
|
|
66
|
+
if (omnia.factory)
|
|
67
|
+
result.push('omnia:factory');
|
|
68
|
+
if (omnia.virtualChannels)
|
|
69
|
+
result.push('omnia:virtual-channels');
|
|
70
|
+
if (omnia.splicing)
|
|
71
|
+
result.push('omnia:splicing');
|
|
72
|
+
if (omnia.hyperswarm)
|
|
73
|
+
result.push('omnia:hyperswarm');
|
|
74
|
+
if (statechain.supported)
|
|
75
|
+
result.push('statechain:supported');
|
|
76
|
+
if (statechain.blindSE)
|
|
77
|
+
result.push('statechain:blind-se');
|
|
78
|
+
if (scripting.kissvm)
|
|
79
|
+
result.push('scripting:kissvm');
|
|
80
|
+
if (qvac.paymentIntents)
|
|
81
|
+
result.push('qvac:payment-intents');
|
|
82
|
+
if (qvac.explanations)
|
|
83
|
+
result.push('qvac:explanations');
|
|
84
|
+
return createCapabilitySet(result);
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const EDGE_VERSION: 1;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const EDGE_VERSION = 1;
|
package/dist/device.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge device factory.
|
|
3
|
+
*/
|
|
4
|
+
import type { EdgeDevice, EdgeDeviceKind } from './types.js';
|
|
5
|
+
export declare function createEdgeDevice(opts: {
|
|
6
|
+
kind: EdgeDeviceKind;
|
|
7
|
+
identityId?: string;
|
|
8
|
+
address?: string;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
}): EdgeDevice;
|
package/dist/device.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge device factory.
|
|
3
|
+
*/
|
|
4
|
+
import { sha3_256 } from '@noble/hashes/sha3.js';
|
|
5
|
+
import { toHex } from './canonical.js';
|
|
6
|
+
export function createEdgeDevice(opts) {
|
|
7
|
+
const { kind, identityId, address, metadata } = opts;
|
|
8
|
+
const ts = Date.now();
|
|
9
|
+
const raw = `edge-device\0${kind}\0${identityId ?? ''}\0${address ?? ''}\0${ts}`;
|
|
10
|
+
const hash = sha3_256(new TextEncoder().encode(raw));
|
|
11
|
+
const deviceId = `edge:device:${toHex(hash)}`;
|
|
12
|
+
return {
|
|
13
|
+
deviceId,
|
|
14
|
+
kind,
|
|
15
|
+
...(identityId !== undefined ? { identityId } : {}),
|
|
16
|
+
...(address !== undefined ? { address } : {}),
|
|
17
|
+
...(metadata !== undefined ? { metadata } : {}),
|
|
18
|
+
createdAt: ts,
|
|
19
|
+
};
|
|
20
|
+
}
|
package/dist/errors.d.ts
ADDED
package/dist/errors.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed errors for @totemsdk/edge.
|
|
3
|
+
*/
|
|
4
|
+
export class EdgeCapabilityError extends Error {
|
|
5
|
+
constructor(capability, message) {
|
|
6
|
+
super(message ?? `Capability not available: ${capability}`);
|
|
7
|
+
this.name = 'EdgeCapabilityError';
|
|
8
|
+
this.code = 'EDGE_CAPABILITY_MISSING';
|
|
9
|
+
this.capability = capability;
|
|
10
|
+
}
|
|
11
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @totemsdk/edge
|
|
3
|
+
*
|
|
4
|
+
* Unified developer-facing runtime for Totem Edge.
|
|
5
|
+
* Composes identity, manifest, wallet/payment/proof/lookup/policy capabilities
|
|
6
|
+
* via injected ports. Adapter-neutral.
|
|
7
|
+
*/
|
|
8
|
+
export { EDGE_VERSION } from './constants.js';
|
|
9
|
+
export { EdgeCapabilityError } from './errors.js';
|
|
10
|
+
export type { EdgeDeviceKind, EdgeOperationResult, EdgeDevice, EdgeRuntime, EdgeProviderProfile, EdgeServiceRegistration, EdgeReceipt, } from './types.js';
|
|
11
|
+
export type { EdgePaymentPort, EdgeLiquidityPort, EdgeProofPort, EdgeLookupPort, EdgePolicyPort, EdgeIdentityPort, EdgeManifestPort, EdgeRuntimePorts, } from './ports.js';
|
|
12
|
+
export type { EdgeCapability, EdgeCapabilitySet } from './capabilities.js';
|
|
13
|
+
export { createCapabilitySet, hasCapability, assertCapability, edgeCapabilitiesFromTotemCapabilities, } from './capabilities.js';
|
|
14
|
+
export { createEdgeRuntime } from './runtime.js';
|
|
15
|
+
export { createEdgeDevice } from './device.js';
|
|
16
|
+
export { createEdgeReceipt, verifyEdgeReceipt } from './receipts.js';
|
|
17
|
+
export { createEdgeProviderProfile, createEdgeServiceRegistration, createEdgeServiceManifest, bindEdgeServiceIdentity, } from './provider.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @totemsdk/edge
|
|
3
|
+
*
|
|
4
|
+
* Unified developer-facing runtime for Totem Edge.
|
|
5
|
+
* Composes identity, manifest, wallet/payment/proof/lookup/policy capabilities
|
|
6
|
+
* via injected ports. Adapter-neutral.
|
|
7
|
+
*/
|
|
8
|
+
export { EDGE_VERSION } from './constants.js';
|
|
9
|
+
export { EdgeCapabilityError } from './errors.js';
|
|
10
|
+
export { createCapabilitySet, hasCapability, assertCapability, edgeCapabilitiesFromTotemCapabilities, } from './capabilities.js';
|
|
11
|
+
export { createEdgeRuntime } from './runtime.js';
|
|
12
|
+
export { createEdgeDevice } from './device.js';
|
|
13
|
+
export { createEdgeReceipt, verifyEdgeReceipt } from './receipts.js';
|
|
14
|
+
export { createEdgeProviderProfile, createEdgeServiceRegistration, createEdgeServiceManifest, bindEdgeServiceIdentity, } from './provider.js';
|
package/dist/ports.d.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port interfaces for @totemsdk/edge.
|
|
3
|
+
*
|
|
4
|
+
* All ports are interfaces only. Callers inject implementations at runtime.
|
|
5
|
+
* @totemsdk/edge ships no proof creation/verification implementations.
|
|
6
|
+
*/
|
|
7
|
+
import type { EdgeOperationResult } from './types.js';
|
|
8
|
+
export interface EdgePaymentPort {
|
|
9
|
+
pay(params: {
|
|
10
|
+
recipient: string;
|
|
11
|
+
amount: string;
|
|
12
|
+
tokenId?: string;
|
|
13
|
+
memo?: string;
|
|
14
|
+
}): Promise<EdgeOperationResult<{
|
|
15
|
+
txpowId?: string;
|
|
16
|
+
}>>;
|
|
17
|
+
}
|
|
18
|
+
export interface EdgeLiquidityPort {
|
|
19
|
+
getBalance(address: string): Promise<EdgeOperationResult<{
|
|
20
|
+
balance: string;
|
|
21
|
+
tokenId: string;
|
|
22
|
+
}>>;
|
|
23
|
+
getUtxos(address: string): Promise<EdgeOperationResult<{
|
|
24
|
+
utxos: unknown[];
|
|
25
|
+
}>>;
|
|
26
|
+
}
|
|
27
|
+
export interface EdgeProofPort {
|
|
28
|
+
createProof(params: {
|
|
29
|
+
subject: string;
|
|
30
|
+
claims: unknown[];
|
|
31
|
+
context?: Record<string, unknown>;
|
|
32
|
+
}): Promise<EdgeOperationResult<{
|
|
33
|
+
proofId: string;
|
|
34
|
+
proof: unknown;
|
|
35
|
+
}>>;
|
|
36
|
+
verifyProof(params: {
|
|
37
|
+
proof: unknown;
|
|
38
|
+
subject?: string;
|
|
39
|
+
}): Promise<EdgeOperationResult<{
|
|
40
|
+
valid: boolean;
|
|
41
|
+
reason?: string;
|
|
42
|
+
}>>;
|
|
43
|
+
}
|
|
44
|
+
export interface EdgeLookupPort {
|
|
45
|
+
lookup(params: {
|
|
46
|
+
query: string;
|
|
47
|
+
kind?: string;
|
|
48
|
+
}): Promise<EdgeOperationResult<{
|
|
49
|
+
results: unknown[];
|
|
50
|
+
}>>;
|
|
51
|
+
watch(params: {
|
|
52
|
+
address: string;
|
|
53
|
+
onUpdate: (data: unknown) => void;
|
|
54
|
+
}): Promise<EdgeOperationResult<{
|
|
55
|
+
unsubscribe: () => void;
|
|
56
|
+
}>>;
|
|
57
|
+
}
|
|
58
|
+
export interface EdgePolicyPort {
|
|
59
|
+
check(params: {
|
|
60
|
+
action: string;
|
|
61
|
+
subject: string;
|
|
62
|
+
context?: Record<string, unknown>;
|
|
63
|
+
}): Promise<EdgeOperationResult<{
|
|
64
|
+
allowed: boolean;
|
|
65
|
+
reason?: string;
|
|
66
|
+
}>>;
|
|
67
|
+
}
|
|
68
|
+
export interface EdgeIdentityPort {
|
|
69
|
+
resolve(identityId: string): Promise<EdgeOperationResult<{
|
|
70
|
+
identity: unknown;
|
|
71
|
+
}>>;
|
|
72
|
+
verify(proof: unknown): Promise<EdgeOperationResult<{
|
|
73
|
+
valid: boolean;
|
|
74
|
+
address?: string;
|
|
75
|
+
}>>;
|
|
76
|
+
}
|
|
77
|
+
export interface EdgeManifestPort {
|
|
78
|
+
sign(manifest: unknown, seed: Uint8Array, keyIndex: number): Promise<EdgeOperationResult<{
|
|
79
|
+
signed: unknown;
|
|
80
|
+
}>>;
|
|
81
|
+
verify(signed: unknown): Promise<EdgeOperationResult<{
|
|
82
|
+
valid: boolean;
|
|
83
|
+
reason?: string;
|
|
84
|
+
}>>;
|
|
85
|
+
}
|
|
86
|
+
export interface EdgeRuntimePorts {
|
|
87
|
+
payment?: EdgePaymentPort;
|
|
88
|
+
liquidity?: EdgeLiquidityPort;
|
|
89
|
+
proof?: EdgeProofPort;
|
|
90
|
+
lookup?: EdgeLookupPort;
|
|
91
|
+
policy?: EdgePolicyPort;
|
|
92
|
+
identity?: EdgeIdentityPort;
|
|
93
|
+
manifest?: EdgeManifestPort;
|
|
94
|
+
}
|
package/dist/ports.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider helper functions for @totemsdk/edge.
|
|
3
|
+
*
|
|
4
|
+
* These functions return data structures only — they do not submit to any registry.
|
|
5
|
+
* Registry, trust-index, watchlist, and lease-coordinator logic remain in
|
|
6
|
+
* @totemsdk/lookup-node and future @totemsdk/proofgraph.
|
|
7
|
+
*/
|
|
8
|
+
import type { EdgeServiceManifest, SignedManifest } from '@totemsdk/manifest';
|
|
9
|
+
import type { IdentityGraph, ManifestIdentityBinding, IdentityProofVerifier } from '@totemsdk/identity';
|
|
10
|
+
import type { EdgeProviderProfile, EdgeServiceRegistration } from './types.js';
|
|
11
|
+
export declare function createEdgeProviderProfile(opts: {
|
|
12
|
+
operatorAddress: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
tags?: string[];
|
|
16
|
+
}): EdgeProviderProfile;
|
|
17
|
+
export declare function createEdgeServiceRegistration(opts: {
|
|
18
|
+
profileId: string;
|
|
19
|
+
serviceId: string;
|
|
20
|
+
operatorAddress: string;
|
|
21
|
+
expiresAt?: number;
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
23
|
+
}): EdgeServiceRegistration;
|
|
24
|
+
export declare function createEdgeServiceManifest(manifest: EdgeServiceManifest, seed: Uint8Array, keyIndex: number): Promise<SignedManifest<EdgeServiceManifest>>;
|
|
25
|
+
export declare function bindEdgeServiceIdentity(signedManifest: SignedManifest<EdgeServiceManifest>, identityGraph: IdentityGraph, options?: {
|
|
26
|
+
proofVerifiers?: Record<string, IdentityProofVerifier>;
|
|
27
|
+
}): Promise<ManifestIdentityBinding>;
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider helper functions for @totemsdk/edge.
|
|
3
|
+
*
|
|
4
|
+
* These functions return data structures only — they do not submit to any registry.
|
|
5
|
+
* Registry, trust-index, watchlist, and lease-coordinator logic remain in
|
|
6
|
+
* @totemsdk/lookup-node and future @totemsdk/proofgraph.
|
|
7
|
+
*/
|
|
8
|
+
import { sha3_256 } from '@noble/hashes/sha3.js';
|
|
9
|
+
import { toHex } from './canonical.js';
|
|
10
|
+
import { signManifest } from '@totemsdk/manifest';
|
|
11
|
+
import { bindManifestToIdentity } from '@totemsdk/identity';
|
|
12
|
+
export function createEdgeProviderProfile(opts) {
|
|
13
|
+
const { operatorAddress, name, description, tags } = opts;
|
|
14
|
+
const ts = Date.now();
|
|
15
|
+
const raw = `edge-provider\0${operatorAddress}\0${name}\0${ts}`;
|
|
16
|
+
const hash = sha3_256(new TextEncoder().encode(raw));
|
|
17
|
+
const profileId = `edge:provider:${toHex(hash)}`;
|
|
18
|
+
return {
|
|
19
|
+
profileId,
|
|
20
|
+
operatorAddress,
|
|
21
|
+
name,
|
|
22
|
+
...(description !== undefined ? { description } : {}),
|
|
23
|
+
tags: tags ?? [],
|
|
24
|
+
createdAt: ts,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function createEdgeServiceRegistration(opts) {
|
|
28
|
+
const { profileId, serviceId, operatorAddress, expiresAt, metadata } = opts;
|
|
29
|
+
const ts = Date.now();
|
|
30
|
+
const raw = `edge-svc-reg\0${profileId}\0${serviceId}\0${operatorAddress}\0${ts}`;
|
|
31
|
+
const hash = sha3_256(new TextEncoder().encode(raw));
|
|
32
|
+
const registrationId = `edge:registration:${toHex(hash)}`;
|
|
33
|
+
return {
|
|
34
|
+
registrationId,
|
|
35
|
+
profileId,
|
|
36
|
+
serviceId,
|
|
37
|
+
operatorAddress,
|
|
38
|
+
registeredAt: ts,
|
|
39
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
40
|
+
...(metadata !== undefined ? { metadata } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export async function createEdgeServiceManifest(manifest, seed, keyIndex) {
|
|
44
|
+
return signManifest(manifest, seed, keyIndex);
|
|
45
|
+
}
|
|
46
|
+
export async function bindEdgeServiceIdentity(signedManifest, identityGraph, options) {
|
|
47
|
+
return bindManifestToIdentity(signedManifest, identityGraph, options);
|
|
48
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge receipt creation and verification.
|
|
3
|
+
*
|
|
4
|
+
* EdgeReceipt is an app/runtime-level receipt. It may reference existing
|
|
5
|
+
* receipt IDs from other layers via relatedManifestId, relatedIdentityId,
|
|
6
|
+
* and payload fields. It does NOT represent chain-level settlement finality.
|
|
7
|
+
*
|
|
8
|
+
* verifyEdgeReceipt always returns a structured EdgeOperationResult, never a bare boolean.
|
|
9
|
+
*/
|
|
10
|
+
import type { EdgeReceipt, EdgeOperationResult } from './types.js';
|
|
11
|
+
export declare function createEdgeReceipt(opts: {
|
|
12
|
+
kind: string;
|
|
13
|
+
payload: Record<string, unknown>;
|
|
14
|
+
relatedManifestId?: string;
|
|
15
|
+
relatedIdentityId?: string;
|
|
16
|
+
issuedAt?: number;
|
|
17
|
+
}): EdgeReceipt;
|
|
18
|
+
export declare function verifyEdgeReceipt(receipt: unknown): EdgeOperationResult<{
|
|
19
|
+
receipt: EdgeReceipt;
|
|
20
|
+
}>;
|
package/dist/receipts.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge receipt creation and verification.
|
|
3
|
+
*
|
|
4
|
+
* EdgeReceipt is an app/runtime-level receipt. It may reference existing
|
|
5
|
+
* receipt IDs from other layers via relatedManifestId, relatedIdentityId,
|
|
6
|
+
* and payload fields. It does NOT represent chain-level settlement finality.
|
|
7
|
+
*
|
|
8
|
+
* verifyEdgeReceipt always returns a structured EdgeOperationResult, never a bare boolean.
|
|
9
|
+
*/
|
|
10
|
+
import { sha3_256 } from '@noble/hashes/sha3.js';
|
|
11
|
+
import { canonicalJson, toHex } from './canonical.js';
|
|
12
|
+
export function createEdgeReceipt(opts) {
|
|
13
|
+
const { kind, payload, relatedManifestId, relatedIdentityId } = opts;
|
|
14
|
+
const issuedAt = opts.issuedAt ?? Date.now();
|
|
15
|
+
const canonical = canonicalJson({ kind, payload, relatedManifestId, relatedIdentityId, issuedAt });
|
|
16
|
+
const hash = sha3_256(new TextEncoder().encode(canonical));
|
|
17
|
+
const receiptId = `edge:receipt:${toHex(hash)}`;
|
|
18
|
+
return {
|
|
19
|
+
receiptId,
|
|
20
|
+
kind,
|
|
21
|
+
issuedAt,
|
|
22
|
+
...(relatedManifestId !== undefined ? { relatedManifestId } : {}),
|
|
23
|
+
...(relatedIdentityId !== undefined ? { relatedIdentityId } : {}),
|
|
24
|
+
payload,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function verifyEdgeReceipt(receipt) {
|
|
28
|
+
if (!receipt || typeof receipt !== 'object') {
|
|
29
|
+
return { ok: false, error: 'receipt is not an object', errorCode: 'INVALID_RECEIPT' };
|
|
30
|
+
}
|
|
31
|
+
const r = receipt;
|
|
32
|
+
if (typeof r.receiptId !== 'string') {
|
|
33
|
+
return { ok: false, error: 'receipt.receiptId must be a string', errorCode: 'INVALID_RECEIPT' };
|
|
34
|
+
}
|
|
35
|
+
if (typeof r.kind !== 'string') {
|
|
36
|
+
return { ok: false, error: 'receipt.kind must be a string', errorCode: 'INVALID_RECEIPT' };
|
|
37
|
+
}
|
|
38
|
+
if (typeof r.issuedAt !== 'number') {
|
|
39
|
+
return { ok: false, error: 'receipt.issuedAt must be a number', errorCode: 'INVALID_RECEIPT' };
|
|
40
|
+
}
|
|
41
|
+
if (!r.payload || typeof r.payload !== 'object') {
|
|
42
|
+
return { ok: false, error: 'receipt.payload must be an object', errorCode: 'INVALID_RECEIPT' };
|
|
43
|
+
}
|
|
44
|
+
return { ok: true, data: { receipt: receipt } };
|
|
45
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge runtime factory.
|
|
3
|
+
*/
|
|
4
|
+
import { EdgeCapabilitySet } from './capabilities.js';
|
|
5
|
+
import type { EdgeRuntimePorts } from './ports.js';
|
|
6
|
+
import type { EdgeRuntime } from './types.js';
|
|
7
|
+
export declare function createEdgeRuntime(opts: {
|
|
8
|
+
deviceId: string;
|
|
9
|
+
capabilities: EdgeCapabilitySet;
|
|
10
|
+
ports: EdgeRuntimePorts;
|
|
11
|
+
}): EdgeRuntime;
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge runtime factory.
|
|
3
|
+
*/
|
|
4
|
+
import { EDGE_VERSION } from './constants.js';
|
|
5
|
+
import { hasCapability, assertCapability, } from './capabilities.js';
|
|
6
|
+
export function createEdgeRuntime(opts) {
|
|
7
|
+
const { deviceId, capabilities, ports } = opts;
|
|
8
|
+
return {
|
|
9
|
+
version: EDGE_VERSION,
|
|
10
|
+
deviceId,
|
|
11
|
+
capabilities,
|
|
12
|
+
ports,
|
|
13
|
+
hasCapability(cap) {
|
|
14
|
+
return hasCapability(capabilities, cap);
|
|
15
|
+
},
|
|
16
|
+
assertCapability(cap) {
|
|
17
|
+
assertCapability(capabilities, cap);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @totemsdk/edge — Type definitions
|
|
3
|
+
*
|
|
4
|
+
* Covers devices, apps, agents, sensors, robots, gateways, and services.
|
|
5
|
+
* Adapter-neutral — no ROS2, no MQTT, no Python bindings.
|
|
6
|
+
*/
|
|
7
|
+
import type { ManifestIdentityBinding } from '@totemsdk/identity';
|
|
8
|
+
import type { SignedManifest, EdgeServiceManifest } from '@totemsdk/manifest';
|
|
9
|
+
export type EdgeDeviceKind = 'device' | 'app' | 'agent' | 'sensor' | 'robot' | 'gateway' | 'service';
|
|
10
|
+
export interface EdgeOperationResult<T = unknown> {
|
|
11
|
+
ok: boolean;
|
|
12
|
+
data?: T;
|
|
13
|
+
error?: string;
|
|
14
|
+
errorCode?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface EdgeDevice {
|
|
17
|
+
deviceId: string;
|
|
18
|
+
kind: EdgeDeviceKind;
|
|
19
|
+
identityId?: string;
|
|
20
|
+
address?: string;
|
|
21
|
+
metadata?: Record<string, unknown>;
|
|
22
|
+
createdAt: number;
|
|
23
|
+
}
|
|
24
|
+
export interface EdgeRuntime {
|
|
25
|
+
version: number;
|
|
26
|
+
deviceId: string;
|
|
27
|
+
capabilities: import('./capabilities.js').EdgeCapabilitySet;
|
|
28
|
+
ports: import('./ports.js').EdgeRuntimePorts;
|
|
29
|
+
hasCapability(cap: import('./capabilities.js').EdgeCapability): boolean;
|
|
30
|
+
assertCapability(cap: import('./capabilities.js').EdgeCapability): void;
|
|
31
|
+
}
|
|
32
|
+
export interface EdgeProviderProfile {
|
|
33
|
+
profileId: string;
|
|
34
|
+
operatorAddress: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
tags: string[];
|
|
38
|
+
createdAt: number;
|
|
39
|
+
}
|
|
40
|
+
export interface EdgeServiceRegistration {
|
|
41
|
+
registrationId: string;
|
|
42
|
+
profileId: string;
|
|
43
|
+
serviceId: string;
|
|
44
|
+
operatorAddress: string;
|
|
45
|
+
registeredAt: number;
|
|
46
|
+
expiresAt?: number;
|
|
47
|
+
metadata?: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
export interface EdgeReceipt {
|
|
50
|
+
receiptId: string;
|
|
51
|
+
kind: string;
|
|
52
|
+
issuedAt: number;
|
|
53
|
+
relatedManifestId?: string;
|
|
54
|
+
relatedIdentityId?: string;
|
|
55
|
+
payload: Record<string, unknown>;
|
|
56
|
+
}
|
|
57
|
+
export type { ManifestIdentityBinding, SignedManifest, EdgeServiceManifest };
|