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

Commit

Permalink
fix: switch delegations
Browse files Browse the repository at this point in the history
  • Loading branch information
hugomrdias committed Oct 28, 2022
1 parent f8ca296 commit 6098bce
Show file tree
Hide file tree
Showing 4 changed files with 5,644 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/commands/delegations/switch.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-ignore
import { Delegation } from '@ucanto/server'
import inquirer from 'inquirer'
import { stringToDelegation } from '../../encoding.js'

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

for (const del of Object.values(delegations)) {
const imported = Delegation.import([del.ucan.root])
const imported = await stringToDelegation(del.ucan) // Delegation.import([del.ucan.root])
choices.push({
name: del.alias + '\t' + imported.issuer.did(),
alias: del.alias,
Expand Down
111 changes: 111 additions & 0 deletions src/encoding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// @ts-nocheck
/* eslint-disable unicorn/prefer-spread */
import { CarReader } from '@ipld/car/reader'
import { CarWriter } from '@ipld/car/writer'
import { Delegation } from '@ucanto/core/delegation'
// eslint-disable-next-line no-unused-vars
import * as Types from '@ucanto/interface'
import * as u8 from 'uint8arrays'

/**
* @param {AsyncIterable<Uint8Array>} iterable
*/
function collector(iterable) {
const chunks = []
const cfn = (async () => {
for await (const chunk of iterable) {
chunks.push(chunk)
}
return u8.concat(chunks)
})()
return cfn
}

/**
* @param {Types.Delegation[]} delegations
* @param {import('uint8arrays/to-string').SupportedEncodings} encoding
*/
export async function encodeDelegations(delegations, encoding = 'base64url') {
if (delegations.length === 0) {
return ''
}

const roots = delegations.map((d) => d.root.cid)

// @ts-ignore
const { writer, out } = CarWriter.create(roots)
const collection = collector(out)

for (const delegation of delegations) {
for (const block of delegation.export()) {
// @ts-ignore
await writer.put(block)
}
}
await writer.close()

const bytes = await collection

return u8.toString(bytes, encoding)
}

/**
* Encode one {@link Types.Delegation Delegation} into a string
*
* @param {Types.Delegation<Types.Capabilities>} delegation
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding]
*/
export function delegationToString(delegation, encoding) {
return encodeDelegations([delegation], encoding)
}

/**
* Decode string into {@link Types.Delegation Delegation}
*
* @template {Types.Capabilities} [T=Types.Capabilities]
* @param {import('./types.js').EncodedDelegation<T>} raw
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding]
*/
export async function decodeDelegations(raw, encoding = 'base64url') {
if (!raw) {
return []
}
const bytes = u8.fromString(raw, encoding)
const reader = await CarReader.fromBytes(bytes)
const roots = await reader.getRoots()

/** @type {Types.Delegation<T>[]} */
const delegations = []

for (const root of roots) {
const rootBlock = await reader.get(root)

if (rootBlock) {
const blocks = new Map()
for (const block of reader._blocks) {
if (block.cid.toString() !== root.toString())
blocks.set(block.cid.toString(), block)
}

// @ts-ignore
delegations.push(new Delegation(rootBlock, blocks))
} else {
throw new Error('Failed to find root from raw delegation.')
}
}

return delegations
}

/**
* Decode string into a {@link Types.Delegation Delegation}
*
* @template {Types.Capabilities} [T=Types.Capabilities]
* @param {import('./types.js').EncodedDelegation<T>} raw
* @param {import('uint8arrays/to-string').SupportedEncodings} [encoding]
*/
export async function stringToDelegation(raw, encoding) {
const delegations = await decodeDelegations(raw, encoding)

return /** @type {Types.Delegation<T>} */ (delegations[0])
}
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Capabilities, Phantom } from '@ucanto/interface'

export type EncodedDelegation<C extends Capabilities = Capabilities> = string &
Phantom<C>
Loading

0 comments on commit 6098bce

Please sign in to comment.