@ixo/ucan 1.0.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/.eslintrc.js +9 -0
- package/.prettierignore +3 -0
- package/.prettierrc.js +4 -0
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +0 -0
- package/README.md +189 -0
- package/dist/capabilities/capability.d.ts +33 -0
- package/dist/capabilities/capability.d.ts.map +1 -0
- package/dist/capabilities/capability.js +53 -0
- package/dist/capabilities/capability.js.map +1 -0
- package/dist/client/create-client.d.ts +33 -0
- package/dist/client/create-client.d.ts.map +1 -0
- package/dist/client/create-client.js +104 -0
- package/dist/client/create-client.js.map +1 -0
- package/dist/did/ixo-resolver.d.ts +8 -0
- package/dist/did/ixo-resolver.d.ts.map +1 -0
- package/dist/did/ixo-resolver.js +162 -0
- package/dist/did/ixo-resolver.js.map +1 -0
- package/dist/did/utils.d.ts +4 -0
- package/dist/did/utils.d.ts.map +1 -0
- package/dist/did/utils.js +85 -0
- package/dist/did/utils.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/store/memory.d.ts +25 -0
- package/dist/store/memory.d.ts.map +1 -0
- package/dist/store/memory.js +71 -0
- package/dist/store/memory.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validator/validator.d.ts +29 -0
- package/dist/validator/validator.d.ts.map +1 -0
- package/dist/validator/validator.js +179 -0
- package/dist/validator/validator.js.map +1 -0
- package/jest.config.js +3 -0
- package/package.json +78 -0
- package/scripts/test-ucan.ts +457 -0
- package/src/capabilities/capability.ts +244 -0
- package/src/client/create-client.ts +329 -0
- package/src/did/ixo-resolver.ts +325 -0
- package/src/did/utils.ts +141 -0
- package/src/index.ts +135 -0
- package/src/store/memory.ts +194 -0
- package/src/types.ts +108 -0
- package/src/validator/validator.ts +399 -0
- package/tsconfig.json +18 -0
package/.eslintrc.js
ADDED
package/.prettierignore
ADDED
package/.prettierrc.js
ADDED
package/CHANGELOG.md
ADDED
|
File without changes
|
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# @ixo/ucan
|
|
2
|
+
|
|
3
|
+
UCAN (User Controlled Authorization Networks) implementation for IXO Services. This package wraps the battle-tested [ucanto](https://github.com/storacha/ucanto) library and provides IXO-specific extensions for DID resolution and MCP tool authorization.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **did:ixo Resolution**: Resolve IXO DIDs to their public keys via the IXO blockchain indexer
|
|
8
|
+
- **MCP Capability Definitions**: Pre-built capability schemas for MCP tool authorization
|
|
9
|
+
- **Server & Client Helpers**: Easy setup for ucanto servers and clients with IXO defaults
|
|
10
|
+
- **Replay Protection**: In-memory invocation store to prevent replay attacks
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @ixo/ucan
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Server-Side (Oracle)
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { createIxoServer, MCPCall } from '@ixo/ucan';
|
|
24
|
+
import { provide } from '@ucanto/server';
|
|
25
|
+
|
|
26
|
+
// Create a handler for MCP tool calls
|
|
27
|
+
const mcpCallHandler = provide(MCPCall, async ({ capability, invocation }) => {
|
|
28
|
+
const { with: resourceUri } = capability;
|
|
29
|
+
|
|
30
|
+
// Parse the resource URI to get server/tool info
|
|
31
|
+
// Format: ixo:oracle:{oracleDid}:mcp/{serverName}/{toolName}
|
|
32
|
+
|
|
33
|
+
// Execute the MCP tool...
|
|
34
|
+
return { ok: { result: 'success' } };
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Create the server
|
|
38
|
+
const { server, did } = createIxoServer({
|
|
39
|
+
privateKey: process.env.ORACLE_PRIVATE_KEY!,
|
|
40
|
+
rootIssuers: [process.env.ADMIN_DID!],
|
|
41
|
+
indexerUrl: 'https://blocksync.ixo.earth/graphql',
|
|
42
|
+
service: {
|
|
43
|
+
mcp: { call: mcpCallHandler }
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
console.log('Server DID:', did);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Client-Side
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { createIxoClient, createMCPResourceURI } from '@ixo/ucan';
|
|
54
|
+
|
|
55
|
+
// Create a client
|
|
56
|
+
const client = createIxoClient({
|
|
57
|
+
privateKey: myPrivateKey,
|
|
58
|
+
serverDid: 'did:key:z6Mk...',
|
|
59
|
+
endpoint: 'https://oracle.ixo.earth/ucan'
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Invoke an MCP tool capability
|
|
63
|
+
const result = await client.invoke({
|
|
64
|
+
can: 'mcp/call',
|
|
65
|
+
with: createMCPResourceURI('did:ixo:oracle123', 'postgres', 'query'),
|
|
66
|
+
nb: { args: { sql: 'SELECT * FROM users' } }
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Or delegate capability to another user
|
|
70
|
+
const delegation = await client.delegate({
|
|
71
|
+
audience: 'did:ixo:alice',
|
|
72
|
+
capabilities: [{
|
|
73
|
+
can: 'mcp/call',
|
|
74
|
+
with: createMCPResourceURI('did:ixo:oracle123', 'postgres', '*')
|
|
75
|
+
}],
|
|
76
|
+
expiration: Math.floor(Date.now() / 1000) + 86400 // 24 hours
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Capability URI Format
|
|
81
|
+
|
|
82
|
+
MCP capabilities use the following URI format:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
ixo:oracle:{oracleDid}:mcp/{serverName}/{toolName}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Examples:
|
|
89
|
+
- `ixo:oracle:did:ixo:abc123:mcp/postgres/query` - Specific tool
|
|
90
|
+
- `ixo:oracle:did:ixo:abc123:mcp/postgres/*` - All tools in server (wildcard)
|
|
91
|
+
- `ixo:oracle:did:ixo:abc123:mcp/*` - All MCP tools (wildcard)
|
|
92
|
+
|
|
93
|
+
## DID Resolution
|
|
94
|
+
|
|
95
|
+
The package supports multiple DID methods:
|
|
96
|
+
|
|
97
|
+
- **did:key** - Handled natively by ucanto
|
|
98
|
+
- **did:ixo** - Resolved via IXO blockchain indexer
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { createIxoDIDResolver, createCompositeDIDResolver } from '@ixo/ucan';
|
|
102
|
+
|
|
103
|
+
const ixoResolver = createIxoDIDResolver({
|
|
104
|
+
indexerUrl: 'https://blocksync.ixo.earth/graphql'
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Create a composite resolver for multiple DID methods
|
|
108
|
+
const resolver = createCompositeDIDResolver([ixoResolver]);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Replay Protection
|
|
112
|
+
|
|
113
|
+
The package includes an in-memory invocation store for replay protection:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { InMemoryInvocationStore } from '@ixo/ucan';
|
|
117
|
+
|
|
118
|
+
const store = new InMemoryInvocationStore({
|
|
119
|
+
defaultTtlMs: 24 * 60 * 60 * 1000, // 24 hours
|
|
120
|
+
cleanupIntervalMs: 60 * 60 * 1000, // 1 hour
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Check if invocation was already used
|
|
124
|
+
if (await store.has(invocationCid)) {
|
|
125
|
+
throw new Error('Replay attack detected');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Mark as used
|
|
129
|
+
await store.add(invocationCid);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Integration with Oracle
|
|
133
|
+
|
|
134
|
+
See the oracle app's `src/ucan/` directory for a complete integration example:
|
|
135
|
+
|
|
136
|
+
- `ucan.config.ts` - Configuration for MCP UCAN requirements
|
|
137
|
+
- `ucan.service.ts` - NestJS service for validation
|
|
138
|
+
- `ucan.module.ts` - NestJS module
|
|
139
|
+
|
|
140
|
+
## Environment Variables
|
|
141
|
+
|
|
142
|
+
For the IXO DID resolver:
|
|
143
|
+
|
|
144
|
+
```env
|
|
145
|
+
BLOCKSYNC_GRAPHQL_URL=https://blocksync.ixo.earth/graphql
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
For UCAN configuration:
|
|
149
|
+
|
|
150
|
+
```env
|
|
151
|
+
ORACLE_ENTITY_DID=did:ixo:your-oracle-did
|
|
152
|
+
UCAN_ROOT_ISSUERS=did:ixo:admin1,did:ixo:admin2
|
|
153
|
+
UCAN_PROTECTED_MCP_SERVERS=postgres,redis
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## API Reference
|
|
157
|
+
|
|
158
|
+
### Types
|
|
159
|
+
|
|
160
|
+
- `IxoDID` - IXO DID type (`did:ixo:${string}`)
|
|
161
|
+
- `KeyDID` - Key DID type (`did:key:${string}`)
|
|
162
|
+
- `MCPResourceURI` - MCP resource URI type
|
|
163
|
+
- `MCPUCANConfig` - Configuration for MCP UCAN requirements
|
|
164
|
+
- `InvocationStore` - Interface for replay protection stores
|
|
165
|
+
- `DIDKeyResolver` - DID resolver function type
|
|
166
|
+
|
|
167
|
+
### Functions
|
|
168
|
+
|
|
169
|
+
- `createIxoServer(options)` - Create a ucanto server with IXO defaults
|
|
170
|
+
- `createIxoClient(options)` - Create a ucanto client with IXO defaults
|
|
171
|
+
- `createIxoDIDResolver(config)` - Create a did:ixo resolver
|
|
172
|
+
- `createCompositeDIDResolver(resolvers)` - Combine multiple DID resolvers
|
|
173
|
+
- `createMCPResourceURI(oracleDid, serverName, toolName)` - Build MCP resource URI
|
|
174
|
+
- `parseMCPResourceURI(uri)` - Parse MCP resource URI into components
|
|
175
|
+
- `createInvocationStore(options)` - Create an invocation store
|
|
176
|
+
|
|
177
|
+
### Capabilities
|
|
178
|
+
|
|
179
|
+
- `MCPCall` - Capability for calling MCP tools
|
|
180
|
+
|
|
181
|
+
## TODO
|
|
182
|
+
|
|
183
|
+
- [ ] Add Redis implementation for distributed deployments
|
|
184
|
+
- [ ] Add SQLite implementation for persistence
|
|
185
|
+
- [ ] Add delegation management utilities
|
|
186
|
+
- [ ] Add capability inspection utilities
|
|
187
|
+
- [ ] Add support for capability revocation lists
|
|
188
|
+
- [ ] Add support for time-based restrictions in caveats
|
|
189
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Schema } from '@ucanto/validator';
|
|
2
|
+
import type { Capability as UcantoCapability } from '@ucanto/interface';
|
|
3
|
+
export { Schema };
|
|
4
|
+
type Infer<T> = T extends {
|
|
5
|
+
read(input: unknown): {
|
|
6
|
+
ok: infer O;
|
|
7
|
+
} | {
|
|
8
|
+
error: unknown;
|
|
9
|
+
};
|
|
10
|
+
} ? O : never;
|
|
11
|
+
type InferStruct<U extends Record<string, unknown>> = {
|
|
12
|
+
[K in keyof U]: Infer<U[K]>;
|
|
13
|
+
};
|
|
14
|
+
export interface DefineCapabilityOptions<NBSchema extends Record<string, any> = Record<string, never>> {
|
|
15
|
+
can: string;
|
|
16
|
+
protocol?: string;
|
|
17
|
+
supportWildcards?: boolean;
|
|
18
|
+
nb?: NBSchema;
|
|
19
|
+
derives?: (claimed: {
|
|
20
|
+
with: string;
|
|
21
|
+
nb?: InferStruct<NBSchema>;
|
|
22
|
+
}, delegated: {
|
|
23
|
+
with: string;
|
|
24
|
+
nb?: InferStruct<NBSchema>;
|
|
25
|
+
}) => {
|
|
26
|
+
ok: Record<string, never>;
|
|
27
|
+
} | {
|
|
28
|
+
error: Error;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export declare function defineCapability<NBSchema extends Record<string, any> = Record<string, never>>(options: DefineCapabilityOptions<NBSchema>): import("@ucanto/interface").TheCapabilityParser<import("@ucanto/interface").CapabilityMatch<`${string}/${string}`, import("@ucanto/interface").URI<`${string}:`>, Schema.InferStruct<{}>>>;
|
|
32
|
+
export type { UcantoCapability, Infer, InferStruct };
|
|
33
|
+
//# sourceMappingURL=capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/capabilities/capability.ts"],"names":[],"mappings":"AAWA,OAAO,EAAmB,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGxE,OAAO,EAAE,MAAM,EAAE,CAAC;AAUlB,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GACpF,CAAC,GACD,KAAK,CAAC;AAMV,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KACnD,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5B,CAAC;AA+BF,MAAM,WAAW,uBAAuB,CAGtC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAM5D,GAAG,EAAE,MAAM,CAAC;IAOZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAOlB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAe3B,EAAE,CAAC,EAAE,QAAQ,CAAC;IAsBd,OAAO,CAAC,EAAE,CACR,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;KAAE,EACrD,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;KAAE,KACpD;QAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CACvD;AAuCD,wBAAgB,gBAAgB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC3F,OAAO,EAAE,uBAAuB,CAAC,QAAQ,CAAC,8LAsE3C;AAGD,YAAY,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { capability, URI, Schema } from '@ucanto/validator';
|
|
2
|
+
export { Schema };
|
|
3
|
+
export function defineCapability(options) {
|
|
4
|
+
const protocol = (options.protocol ?? 'urn:');
|
|
5
|
+
const supportWildcards = options.supportWildcards ?? true;
|
|
6
|
+
const nbSchema = options.nb
|
|
7
|
+
? Schema.struct(options.nb)
|
|
8
|
+
: Schema.struct({});
|
|
9
|
+
return capability({
|
|
10
|
+
can: options.can,
|
|
11
|
+
with: URI.match({ protocol }),
|
|
12
|
+
nb: nbSchema,
|
|
13
|
+
derives: (claimed, delegated) => {
|
|
14
|
+
const claimedUri = claimed.with;
|
|
15
|
+
const delegatedUri = delegated.with;
|
|
16
|
+
if (claimedUri !== delegatedUri) {
|
|
17
|
+
if (supportWildcards) {
|
|
18
|
+
if (delegatedUri.endsWith('/*')) {
|
|
19
|
+
const baseUri = delegatedUri.slice(0, -1);
|
|
20
|
+
if (!claimedUri.startsWith(baseUri)) {
|
|
21
|
+
return {
|
|
22
|
+
error: new Error(`Resource '${claimedUri}' not covered by '${delegatedUri}'`),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else if (delegatedUri.endsWith(':*')) {
|
|
27
|
+
const baseUri = delegatedUri.slice(0, -1);
|
|
28
|
+
if (!claimedUri.startsWith(baseUri)) {
|
|
29
|
+
return {
|
|
30
|
+
error: new Error(`Resource '${claimedUri}' not covered by '${delegatedUri}'`),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
return {
|
|
36
|
+
error: new Error(`Resource '${claimedUri}' does not match '${delegatedUri}'`),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return {
|
|
42
|
+
error: new Error(`Resource '${claimedUri}' does not match '${delegatedUri}'`),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (options.derives) {
|
|
47
|
+
return options.derives({ with: claimedUri, nb: claimed.nb }, { with: delegatedUri, nb: delegated.nb });
|
|
48
|
+
}
|
|
49
|
+
return { ok: {} };
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../../src/capabilities/capability.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI5D,OAAO,EAAE,MAAM,EAAE,CAAC;AA0JlB,MAAM,UAAU,gBAAgB,CAC9B,OAA0C;IAE1C,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAiB,CAAC;IAC9D,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAG1D,MAAM,QAAQ,GAAG,OAAO,CAAC,EAAE;QACzB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAyC,CAAC;QAClE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAEtB,OAAO,UAAU,CAAC;QAChB,GAAG,EAAE,OAAO,CAAC,GAA4B;QACzC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;QAC7B,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE;YAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;YAChC,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC;YAGpC,IAAI,UAAU,KAAK,YAAY,EAAE,CAAC;gBAEhC,IAAI,gBAAgB,EAAE,CAAC;oBAErB,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;wBAChC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;wBAC1C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;4BACpC,OAAO;gCACL,KAAK,EAAE,IAAI,KAAK,CACd,aAAa,UAAU,qBAAqB,YAAY,GAAG,CAC5D;6BACF,CAAC;wBACJ,CAAC;oBACH,CAAC;yBAEI,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;wBACrC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;wBAC1C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;4BACpC,OAAO;gCACL,KAAK,EAAE,IAAI,KAAK,CACd,aAAa,UAAU,qBAAqB,YAAY,GAAG,CAC5D;6BACF,CAAC;wBACJ,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,OAAO;4BACL,KAAK,EAAE,IAAI,KAAK,CACd,aAAa,UAAU,qBAAqB,YAAY,GAAG,CAC5D;yBACF,CAAC;oBACJ,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,OAAO;wBACL,KAAK,EAAE,IAAI,KAAK,CACd,aAAa,UAAU,qBAAqB,YAAY,GAAG,CAC5D;qBACF,CAAC;gBACJ,CAAC;YACH,CAAC;YAGD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,OAAO,CAAC,OAAO,CACpB,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,CAAC,EAA2B,EAAE,EAC7D,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS,CAAC,EAA2B,EAAE,CAClE,CAAC;YACJ,CAAC;YAED,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QACpB,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as Client from '@ucanto/client';
|
|
2
|
+
import type { Signer, Delegation, Capability } from '@ucanto/interface';
|
|
3
|
+
import type { SupportedDID } from '../types.js';
|
|
4
|
+
export declare function generateKeypair(): Promise<{
|
|
5
|
+
signer: Signer;
|
|
6
|
+
did: string;
|
|
7
|
+
privateKey: string;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function parseSigner(privateKey: string, did?: SupportedDID): Signer;
|
|
10
|
+
export declare function signerFromMnemonic(mnemonic: string, did?: SupportedDID): Promise<{
|
|
11
|
+
signer: Signer;
|
|
12
|
+
did: string;
|
|
13
|
+
privateKey: string;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function createDelegation(options: {
|
|
16
|
+
issuer: Signer;
|
|
17
|
+
audience: string;
|
|
18
|
+
capabilities: Capability[];
|
|
19
|
+
expiration?: number;
|
|
20
|
+
notBefore?: number;
|
|
21
|
+
proofs?: Delegation[];
|
|
22
|
+
}): Promise<Delegation>;
|
|
23
|
+
export declare function createInvocation(options: {
|
|
24
|
+
issuer: Signer;
|
|
25
|
+
audience: string;
|
|
26
|
+
capability: Capability;
|
|
27
|
+
proofs?: Delegation[];
|
|
28
|
+
}): Promise<Client.IssuedInvocationView<Client.Capability<Client.Ability, `${string}:${string}`, unknown>>>;
|
|
29
|
+
export declare function serializeInvocation(invocation: Awaited<ReturnType<typeof createInvocation>>): Promise<string>;
|
|
30
|
+
export declare function serializeDelegation(delegation: Delegation): Promise<string>;
|
|
31
|
+
export declare function parseDelegation(serialized: string): Promise<Delegation>;
|
|
32
|
+
export type { Signer, Delegation, Capability };
|
|
33
|
+
//# sourceMappingURL=create-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-client.d.ts","sourceRoot":"","sources":["../../src/client/create-client.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAEzC,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmChD,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAOD;AASD,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,MAAM,CAM1E;AAqBD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAkDD;AA2BD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAE9C,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,MAAM,CAAC;IAEjB,YAAY,EAAE,UAAU,EAAE,CAAC;IAE3B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,GAAG,OAAO,CAAC,UAAU,CAAC,CAatB;AA6BD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAE9C,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,MAAM,CAAC;IAEjB,UAAU,EAAE,UAAU,CAAC;IAEvB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,2GAUA;AAQD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,GACvD,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAQD,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAejF;AAQD,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB7E;AAGD,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as Client from '@ucanto/client';
|
|
2
|
+
import { ed25519 } from '@ucanto/principal';
|
|
3
|
+
function createPrincipal(did) {
|
|
4
|
+
if (did.startsWith('did:key:')) {
|
|
5
|
+
return ed25519.Verifier.parse(did);
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
did: () => did,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export async function generateKeypair() {
|
|
12
|
+
const signer = await ed25519.Signer.generate();
|
|
13
|
+
return {
|
|
14
|
+
signer,
|
|
15
|
+
did: signer.did(),
|
|
16
|
+
privateKey: ed25519.Signer.format(signer),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function parseSigner(privateKey, did) {
|
|
20
|
+
const signer = ed25519.Signer.parse(privateKey);
|
|
21
|
+
if (did) {
|
|
22
|
+
return signer.withDID(did);
|
|
23
|
+
}
|
|
24
|
+
return signer;
|
|
25
|
+
}
|
|
26
|
+
export async function signerFromMnemonic(mnemonic, did) {
|
|
27
|
+
const { Ed25519, sha256 } = await import('@cosmjs/crypto');
|
|
28
|
+
const { toUtf8 } = await import('@cosmjs/encoding');
|
|
29
|
+
const seed = sha256(toUtf8(mnemonic.trim())).slice(0, 32);
|
|
30
|
+
const keypair = await Ed25519.makeKeypair(seed);
|
|
31
|
+
const ED25519_PRIV_MULTICODEC = new Uint8Array([0x80, 0x26]);
|
|
32
|
+
const ED25519_PUB_MULTICODEC = new Uint8Array([0xed, 0x01]);
|
|
33
|
+
const keyMaterial = new Uint8Array(ED25519_PRIV_MULTICODEC.length +
|
|
34
|
+
seed.length +
|
|
35
|
+
ED25519_PUB_MULTICODEC.length +
|
|
36
|
+
keypair.pubkey.length);
|
|
37
|
+
keyMaterial.set(ED25519_PRIV_MULTICODEC, 0);
|
|
38
|
+
keyMaterial.set(seed, ED25519_PRIV_MULTICODEC.length);
|
|
39
|
+
keyMaterial.set(ED25519_PUB_MULTICODEC, ED25519_PRIV_MULTICODEC.length + seed.length);
|
|
40
|
+
keyMaterial.set(keypair.pubkey, ED25519_PRIV_MULTICODEC.length + seed.length + ED25519_PUB_MULTICODEC.length);
|
|
41
|
+
const base64 = Buffer.from(keyMaterial).toString('base64');
|
|
42
|
+
const multibasePrivateKey = 'M' + base64;
|
|
43
|
+
let signer = ed25519.Signer.parse(multibasePrivateKey);
|
|
44
|
+
const finalSigner = did ? signer.withDID(did) : signer;
|
|
45
|
+
return {
|
|
46
|
+
signer: finalSigner,
|
|
47
|
+
did: finalSigner.did(),
|
|
48
|
+
privateKey: multibasePrivateKey,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export async function createDelegation(options) {
|
|
52
|
+
const audiencePrincipal = createPrincipal(options.audience);
|
|
53
|
+
return Client.delegate({
|
|
54
|
+
issuer: options.issuer,
|
|
55
|
+
audience: audiencePrincipal,
|
|
56
|
+
capabilities: options.capabilities,
|
|
57
|
+
expiration: options.expiration,
|
|
58
|
+
proofs: options.proofs,
|
|
59
|
+
notBefore: options.notBefore,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
export async function createInvocation(options) {
|
|
63
|
+
const audiencePrincipal = createPrincipal(options.audience);
|
|
64
|
+
return Client.invoke({
|
|
65
|
+
issuer: options.issuer,
|
|
66
|
+
audience: audiencePrincipal,
|
|
67
|
+
capability: options.capability,
|
|
68
|
+
proofs: options.proofs ?? [],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
export async function serializeInvocation(invocation) {
|
|
72
|
+
const built = await invocation.buildIPLDView();
|
|
73
|
+
const archive = await built.archive();
|
|
74
|
+
if (archive.error) {
|
|
75
|
+
throw new Error(`Failed to archive invocation: ${archive.error?.message ?? 'unknown'}`);
|
|
76
|
+
}
|
|
77
|
+
if (!archive.ok) {
|
|
78
|
+
throw new Error('Failed to archive invocation: no data returned');
|
|
79
|
+
}
|
|
80
|
+
return Buffer.from(archive.ok).toString('base64');
|
|
81
|
+
}
|
|
82
|
+
export async function serializeDelegation(delegation) {
|
|
83
|
+
const archive = await delegation.archive();
|
|
84
|
+
if (archive.error) {
|
|
85
|
+
throw new Error(`Failed to archive delegation: ${archive.error.message}`);
|
|
86
|
+
}
|
|
87
|
+
if (!archive.ok) {
|
|
88
|
+
throw new Error('Failed to archive delegation: no data returned');
|
|
89
|
+
}
|
|
90
|
+
return Buffer.from(archive.ok).toString('base64');
|
|
91
|
+
}
|
|
92
|
+
export async function parseDelegation(serialized) {
|
|
93
|
+
const { extract } = await import('@ucanto/core/delegation');
|
|
94
|
+
const bytes = new Uint8Array(Buffer.from(serialized, 'base64'));
|
|
95
|
+
const result = await extract(bytes);
|
|
96
|
+
if (result.error) {
|
|
97
|
+
throw new Error(`Failed to parse delegation: ${result.error?.message ?? 'unknown error'}`);
|
|
98
|
+
}
|
|
99
|
+
if (!result.ok) {
|
|
100
|
+
throw new Error('Failed to parse delegation: no data returned');
|
|
101
|
+
}
|
|
102
|
+
return result.ok;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=create-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-client.js","sourceRoot":"","sources":["../../src/client/create-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DIDKeyResolver } from '../types.js';
|
|
2
|
+
export interface IxoDIDResolverConfig {
|
|
3
|
+
indexerUrl: string;
|
|
4
|
+
fetch?: typeof globalThis.fetch;
|
|
5
|
+
}
|
|
6
|
+
export declare function createIxoDIDResolver(config: IxoDIDResolverConfig): DIDKeyResolver;
|
|
7
|
+
export declare function createCompositeDIDResolver(resolvers: DIDKeyResolver[]): DIDKeyResolver;
|
|
8
|
+
//# sourceMappingURL=ixo-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ixo-resolver.d.ts","sourceRoot":"","sources":["../../src/did/ixo-resolver.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAU,MAAM,aAAa,CAAC;AAM1D,MAAM,WAAW,oBAAoB;IAKnC,UAAU,EAAE,MAAM,CAAC;IAKnB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAwJD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,oBAAoB,GAC3B,cAAc,CA2GhB;AAQD,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,cAAc,EAAE,GAC1B,cAAc,CAuBhB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { base58Encode, hexDecode, base58Decode } from './utils.js';
|
|
2
|
+
const DID_DOCUMENT_QUERY = `
|
|
3
|
+
query GetDIDDocument($id: String!) {
|
|
4
|
+
iids(filter: { id: { equalTo: $id } }) {
|
|
5
|
+
nodes {
|
|
6
|
+
id
|
|
7
|
+
verificationMethod
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
const ED25519_MULTICODEC_PREFIX = new Uint8Array([0xed, 0x01]);
|
|
13
|
+
function rawPublicKeyToDidKey(publicKeyBytes) {
|
|
14
|
+
if (publicKeyBytes.length !== 32) {
|
|
15
|
+
console.warn(`[IxoDIDResolver] Expected 32-byte Ed25519 key, got ${publicKeyBytes.length} bytes`);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const prefixedKey = new Uint8Array(ED25519_MULTICODEC_PREFIX.length + publicKeyBytes.length);
|
|
19
|
+
prefixedKey.set(ED25519_MULTICODEC_PREFIX, 0);
|
|
20
|
+
prefixedKey.set(publicKeyBytes, ED25519_MULTICODEC_PREFIX.length);
|
|
21
|
+
const multibaseEncoded = 'z' + base58Encode(prefixedKey);
|
|
22
|
+
return `did:key:${multibaseEncoded}`;
|
|
23
|
+
}
|
|
24
|
+
function publicKeyToDidKey(vm) {
|
|
25
|
+
if (vm.publicKeyMultibase) {
|
|
26
|
+
if (vm.publicKeyMultibase.startsWith('z')) {
|
|
27
|
+
return `did:key:${vm.publicKeyMultibase}`;
|
|
28
|
+
}
|
|
29
|
+
console.warn(`[IxoDIDResolver] Unsupported multibase prefix for ${vm.id}: ${vm.publicKeyMultibase.charAt(0)}`);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
if (vm.publicKeyHex) {
|
|
33
|
+
try {
|
|
34
|
+
const publicKeyBytes = hexDecode(vm.publicKeyHex);
|
|
35
|
+
const didKey = rawPublicKeyToDidKey(publicKeyBytes);
|
|
36
|
+
return didKey;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.warn(`[IxoDIDResolver] Failed to decode publicKeyHex for ${vm.id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (vm.publicKeyBase58) {
|
|
44
|
+
try {
|
|
45
|
+
const publicKeyBytes = base58Decode(vm.publicKeyBase58);
|
|
46
|
+
const didKey = rawPublicKeyToDidKey(publicKeyBytes);
|
|
47
|
+
return didKey;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.warn(`[IxoDIDResolver] Failed to decode publicKeyBase58 for ${vm.id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
export function createIxoDIDResolver(config) {
|
|
57
|
+
const fetchFn = config.fetch ?? globalThis.fetch;
|
|
58
|
+
return async (did) => {
|
|
59
|
+
if (!did.startsWith('did:ixo:')) {
|
|
60
|
+
return {
|
|
61
|
+
error: {
|
|
62
|
+
name: 'DIDKeyResolutionError',
|
|
63
|
+
did,
|
|
64
|
+
message: `Cannot resolve ${did}: not a did:ixo identifier`,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const response = await fetchFn(config.indexerUrl, {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: {
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
},
|
|
74
|
+
body: JSON.stringify({
|
|
75
|
+
query: DID_DOCUMENT_QUERY,
|
|
76
|
+
variables: { id: did },
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
return {
|
|
81
|
+
error: {
|
|
82
|
+
name: 'DIDKeyResolutionError',
|
|
83
|
+
did,
|
|
84
|
+
message: `Failed to fetch DID document: HTTP ${response.status}`,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const data = (await response.json());
|
|
89
|
+
if (data.errors && data.errors.length > 0) {
|
|
90
|
+
return {
|
|
91
|
+
error: {
|
|
92
|
+
name: 'DIDKeyResolutionError',
|
|
93
|
+
did,
|
|
94
|
+
message: `GraphQL error: ${data.errors[0]?.message ?? 'Unknown error'}`,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const didDoc = data.data?.iids?.nodes?.[0];
|
|
99
|
+
if (!didDoc) {
|
|
100
|
+
return {
|
|
101
|
+
error: {
|
|
102
|
+
name: 'DIDKeyResolutionError',
|
|
103
|
+
did,
|
|
104
|
+
message: `DID document not found for ${did}`,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const keys = [];
|
|
109
|
+
for (const vm of didDoc.verificationMethod || []) {
|
|
110
|
+
if (vm.type.includes('Ed25519') ||
|
|
111
|
+
vm.type === 'JsonWebKey2020' ||
|
|
112
|
+
vm.id.includes('signing')) {
|
|
113
|
+
const keyDid = publicKeyToDidKey(vm);
|
|
114
|
+
if (keyDid) {
|
|
115
|
+
keys.push(keyDid);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (keys.length === 0) {
|
|
120
|
+
return {
|
|
121
|
+
error: {
|
|
122
|
+
name: 'DIDKeyResolutionError',
|
|
123
|
+
did,
|
|
124
|
+
message: `No valid Ed25519 verification methods found in DID document for ${did}`,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return { ok: keys };
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
return {
|
|
132
|
+
error: {
|
|
133
|
+
name: 'DIDKeyResolutionError',
|
|
134
|
+
did,
|
|
135
|
+
message: `Failed to resolve ${did}: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export function createCompositeDIDResolver(resolvers) {
|
|
142
|
+
return async (did) => {
|
|
143
|
+
for (const resolver of resolvers) {
|
|
144
|
+
const result = await resolver(did);
|
|
145
|
+
if ('ok' in result) {
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
if (result.error.message.includes('not a did:')) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
error: {
|
|
155
|
+
name: 'DIDKeyResolutionError',
|
|
156
|
+
did,
|
|
157
|
+
message: `No resolver could handle ${did}`,
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=ixo-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ixo-resolver.js","sourceRoot":"","sources":["../../src/did/ixo-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/did/utils.ts"],"names":[],"mappings":"AAkBA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAgDpD;AAOD,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA2CtD;AASD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAcjD"}
|