Skip to content
This repository was archived by the owner on Dec 14, 2022. It is now read-only.

Commit 6098bce

Browse files
committed
fix: switch delegations
1 parent f8ca296 commit 6098bce

File tree

4 files changed

+5644
-1
lines changed

4 files changed

+5644
-1
lines changed

src/commands/delegations/switch.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @ts-ignore
22
import { Delegation } from '@ucanto/server'
33
import inquirer from 'inquirer'
4+
import { stringToDelegation } from '../../encoding.js'
45

56
import { getClient } from '../../client.js'
67
import { hasID } from '../../validation.js'
@@ -27,7 +28,7 @@ const handler = async ({ did, alias, profile }) => {
2728
let choices = []
2829

2930
for (const del of Object.values(delegations)) {
30-
const imported = Delegation.import([del.ucan.root])
31+
const imported = await stringToDelegation(del.ucan) // Delegation.import([del.ucan.root])
3132
choices.push({
3233
name: del.alias + '\t' + imported.issuer.did(),
3334
alias: del.alias,

src/encoding.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// @ts-nocheck
2+
/* eslint-disable unicorn/prefer-spread */
3+
import { CarReader } from '@ipld/car/reader'
4+
import { CarWriter } from '@ipld/car/writer'
5+
import { Delegation } from '@ucanto/core/delegation'
6+
// eslint-disable-next-line no-unused-vars
7+
import * as Types from '@ucanto/interface'
8+
import * as u8 from 'uint8arrays'
9+
10+
/**
11+
* @param {AsyncIterable<Uint8Array>} iterable
12+
*/
13+
function collector(iterable) {
14+
const chunks = []
15+
const cfn = (async () => {
16+
for await (const chunk of iterable) {
17+
chunks.push(chunk)
18+
}
19+
return u8.concat(chunks)
20+
})()
21+
return cfn
22+
}
23+
24+
/**
25+
* @param {Types.Delegation[]} delegations
26+
* @param {import('uint8arrays/to-string').SupportedEncodings} encoding
27+
*/
28+
export async function encodeDelegations(delegations, encoding = 'base64url') {
29+
if (delegations.length === 0) {
30+
return ''
31+
}
32+
33+
const roots = delegations.map((d) => d.root.cid)
34+
35+
// @ts-ignore
36+
const { writer, out } = CarWriter.create(roots)
37+
const collection = collector(out)
38+
39+
for (const delegation of delegations) {
40+
for (const block of delegation.export()) {
41+
// @ts-ignore
42+
await writer.put(block)
43+
}
44+
}
45+
await writer.close()
46+
47+
const bytes = await collection
48+
49+
return u8.toString(bytes, encoding)
50+
}
51+
52+
/**
53+
* Encode one {@link Types.Delegation Delegation} into a string
54+
*
55+
* @param {Types.Delegation<Types.Capabilities>} delegation
56+
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding]
57+
*/
58+
export function delegationToString(delegation, encoding) {
59+
return encodeDelegations([delegation], encoding)
60+
}
61+
62+
/**
63+
* Decode string into {@link Types.Delegation Delegation}
64+
*
65+
* @template {Types.Capabilities} [T=Types.Capabilities]
66+
* @param {import('./types.js').EncodedDelegation<T>} raw
67+
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding]
68+
*/
69+
export async function decodeDelegations(raw, encoding = 'base64url') {
70+
if (!raw) {
71+
return []
72+
}
73+
const bytes = u8.fromString(raw, encoding)
74+
const reader = await CarReader.fromBytes(bytes)
75+
const roots = await reader.getRoots()
76+
77+
/** @type {Types.Delegation<T>[]} */
78+
const delegations = []
79+
80+
for (const root of roots) {
81+
const rootBlock = await reader.get(root)
82+
83+
if (rootBlock) {
84+
const blocks = new Map()
85+
for (const block of reader._blocks) {
86+
if (block.cid.toString() !== root.toString())
87+
blocks.set(block.cid.toString(), block)
88+
}
89+
90+
// @ts-ignore
91+
delegations.push(new Delegation(rootBlock, blocks))
92+
} else {
93+
throw new Error('Failed to find root from raw delegation.')
94+
}
95+
}
96+
97+
return delegations
98+
}
99+
100+
/**
101+
* Decode string into a {@link Types.Delegation Delegation}
102+
*
103+
* @template {Types.Capabilities} [T=Types.Capabilities]
104+
* @param {import('./types.js').EncodedDelegation<T>} raw
105+
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding]
106+
*/
107+
export async function stringToDelegation(raw, encoding) {
108+
const delegations = await decodeDelegations(raw, encoding)
109+
110+
return /** @type {Types.Delegation<T>} */ (delegations[0])
111+
}

src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import type { Capabilities, Phantom } from '@ucanto/interface'
2+
3+
export type EncodedDelegation<C extends Capabilities = Capabilities> = string &
4+
Phantom<C>

0 commit comments

Comments
 (0)