Skip to content

[Bug] : Key import  #233

@FournyP

Description

@FournyP

Hi everyone,

I just find a bug in the key import method while trying it for one of my project.

I have the following error using kubo v0.28.0 :
Uncaught HTTPError HTTPError: file argument 'key' is required

After investigation, i've see that the parameters are not corresponding.

Actual method signature : import(name: string, pem: string, password: string, options?: HTTPRPCOptions): Promise<Key>

Expected method following the API doc : import(name: string, file: File, ipnsBase?: string, format?: string, allowAnyKeyType?: boolean, options?: HTTPRPCOptions): Promise<Key>;

Here the link of the documentation :
https://docs-ipfs-tech.ipns.dweb.link/reference/kubo/rpc/#api-v0-key-import

I wanted to do a PR but I don't have aegir on my computer and I don't know how it work at all
I've also seen that there is tests inside test\interface-tests\src\key and I don't have time to spend on this.

Here a little workaround to fix this issue :

// File src/key/index.ts
import { createGen } from './gen.js'
import { createImport } from './import.js'
import { createList } from './list.js'
import { createRename } from './rename.js'
import { createRm } from './rm.js'
import type { HTTPRPCOptions } from '../index.js'
import type { HTTPRPCClient } from '../lib/core.js'

export type KeyType = 'ed25519' | 'rsa'

export interface KeyGenOptions extends HTTPRPCOptions {
  type?: KeyType
  size?: number
  'ipns-base'?: string
}

export interface Key {
  id: string
  name: string
}

export interface KeyRenameResult {
  id: string
  was: string
  now: string
  overwrite: boolean
}

export interface KeyAPI {
  /**
   * Generate a new key
   *
   * @example
   * ```js
   * const key = await ipfs.key.gen('my-key', {
   *   type: 'rsa',
   *   size: 2048
   * })
   *
   * console.log(key)
   * // { id: 'QmYWqAFvLWb2G5A69JGXui2JJXzaHXiUEmQkQgor6kNNcJ',
   * //  name: 'my-key' }
   * ```
   */
  gen(name: string, options?: KeyGenOptions): Promise<Key>

  /**
   * List all the keys
   *
   * @example
   * ```js
   * const keys = await ipfs.key.list()
   *
   * console.log(keys)
   * // [
   * //   { id: 'QmTe4tuceM2sAmuZiFsJ9tmAopA8au71NabBDdpPYDjxAb',
   * //     name: 'self' },
   * //   { id: 'QmWETF5QvzGnP7jKq5sPDiRjSM2fzwzNsna4wSBEzRzK6W',
   * //     name: 'my-key' }
   * // ]
   * ```
   */
  list(options?: HTTPRPCOptions): Promise<Key[]>

  /**
   * Remove a key
   *
   * @example
   * ```js
   * const key = await ipfs.key.rm('my-key')
   *
   * console.log(key)
   * // { id: 'QmWETF5QvzGnP7jKq5sPDiRjSM2fzwzNsna4wSBEzRzK6W',
   * //   name: 'my-key' }
   * ```
   */
  rm(name: string, options?: HTTPRPCOptions): Promise<Key>

  /**
   * Rename a key
   *
   * @example
   * ```js
   * const key = await ipfs.key.rename('my-key', 'my-new-key')
   *
   * console.log(key)
   * // { id: 'Qmd4xC46Um6s24MradViGLFtMitvrR4SVexKUgPgFjMNzg',
   * //   was: 'my-key',
   * //   now: 'my-new-key',
   * //   overwrite: false }
   * ```
   */
  rename(oldName: string, newName: string, options?: HTTPRPCOptions): Promise<KeyRenameResult>

  /**
   * Remove a key
   *
   * @example
   * ```js
   * const key = await ipfs.key.import('clone', file)
   *
   * console.log(key)
   * // { id: 'QmQRiays958UM7norGRQUG3tmrLq8pJdmJarwYSk2eLthQ',
   * //   name: 'clone' }
   * ```
   */
  import(name: string, file: File, ipnsBase?: string, format?: string, allowAnyKeyType?: boolean, options?: HTTPRPCOptions): Promise<Key>;
}

export function createKey (client: HTTPRPCClient): KeyAPI {
  return {
    gen: createGen(client),
    import: createImport(client),
    list: createList(client),
    rename: createRename(client),
    rm: createRm(client)
  }
}
// File src/key/import.ts
import { objectToCamel } from '../lib/object-to-camel.js'
import { toUrlSearchParams } from '../lib/to-url-search-params.js'
import type { KeyAPI } from './index.js'
import type { HTTPRPCClient } from '../lib/core.js'

export function createImport (client: HTTPRPCClient): KeyAPI['import'] {
  return async function importKey (name, file, ipnsBase?, format?, allowAnyKeyType?, options = {}) {
    const body = new FormData()
    body.append('file', file)

    const res = await client.post('key/import', {
      signal: options.signal,
      searchParams: toUrlSearchParams({
        arg: name,
        'ipns-base': ipnsBase,
        format,
        'allow-any-key-type': allowAnyKeyType,
        ...options
      }),
      body,
      headers: {
       ...options.headers,
       "Content-Type": "multipart/form-data"
      }
    })
    const data = await res.json()

    return objectToCamel(data)
  }
}

Have a nice day and thanks for your work !

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions