ipfs / js-kubo-rpc-client

A client library for the Kubo RPC API
https://www.npmjs.com/package/kubo-rpc-client
Other
33 stars 7 forks source link

[Bug] : Key import #233

Open FournyP opened 5 months ago

FournyP commented 5 months ago

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 !