Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/solid-heads-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@lit-protocol/lit-client': minor
---

LitClient now offers `getIpfsId` via `@lit-protocol/lit-client/ipfs`, letting apps compute CIDv0 hashes (e.g., `await getIpfsId('hello')`) while keeping bundles lean.

```ts
import { getIpfsId } from '@lit-protocol/lit-client/ipfs';
const cid = await getIpfsId('hello');
```
5 changes: 3 additions & 2 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@
]
},
{
"group": "Access Control Conditions",
"group": "Utilities",
"pages": [
"sdk/sdk-reference/access-control-conditions/functions/createAccBuilder"
"sdk/sdk-reference/access-control-conditions/functions/createAccBuilder",
"sdk/sdk-reference/lit-client/functions/getIpfsId"
]
},
{
Expand Down
32 changes: 32 additions & 0 deletions docs/sdk/sdk-reference/lit-client/functions/getIpfsId.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: getIpfsId
description: Generate CIDv0 hashes with the Lit Client IPFS helper
---

## Overview

`getIpfsId` is an optional helper exported via `@lit-protocol/lit-client/ipfs`. It produces CIDv0 IPFS identifiers identical to the Lit SDK v7 utility while remaining fully tree-shakeable from the main client bundle.

## Usage

```ts
import { getIpfsId } from '@lit-protocol/lit-client/ipfs';

const cid = await getIpfsId('console.log("hello lit")');
// cid === 'Qm...'
```

## Parameters

| Name | Type | Description |
| ---- | ---- | ----------- |
| input | `string` | Source content to hash. Mirrors the v7 helper contract by accepting plain strings. |

## Returns

- `Promise<\`Qm${string}\`>` – A CIDv0 string beginning with `Qm`.

## Notes

- The helper delegates to the same hashing routine used in v7 (`typestub-ipfs-only-hash`) and can be imported without pulling the entire Lit Client into your bundle.
- If you need to hash binary data, convert it to a string representation (for example, base64) before passing it to `getIpfsId`.
2 changes: 2 additions & 0 deletions packages/lit-client/ipfs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { getIpfsId } from '../src/ipfs/getIpfsId';
export type { IpfsCidV0 } from '../src/ipfs/getIpfsId';
1 change: 1 addition & 0 deletions packages/lit-client/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export default {
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/packages/lit-client',
setupFilesAfterEnv: ['../../jest.setup.js'],
testEnvironment: 'node',
};
20 changes: 20 additions & 0 deletions packages/lit-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,29 @@
"main": "./index.js",
"typings": "./index.d.ts",
"types": "./index.d.ts",
"exports": {
".": {
"types": "./index.d.ts",
"require": "./index.js",
"import": "./index.js"
},
"./ipfs": {
"types": "./ipfs/index.d.ts",
"require": "./ipfs/index.js",
"import": "./ipfs/index.js"
}
},
"typesVersions": {
"*": {
"ipfs": [
"ipfs/index.d.ts"
]
}
},
"dependencies": {
"@lit-protocol/uint8arrays": "7.1.1",
"bs58": "^6.0.0",
"typestub-ipfs-only-hash": "^4.0.0",
"zod": "3.24.3"
},
"peerDependencies": {
Expand Down
25 changes: 25 additions & 0 deletions packages/lit-client/src/ipfs/getIpfsId.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { getIpfsId } from './getIpfsId';

const encoder = new TextEncoder();

describe('getIpfsId', () => {
it('creates a CIDv0 for string input', async () => {
await expect(getIpfsId('hello')).resolves.toBe(
'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX'
);
});

it('creates the same CIDv0 for byte input', async () => {
const bytes = encoder.encode('hello');
await expect(getIpfsId(bytes)).resolves.toBe(
'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX'
);
});

it('throws when input type is unsupported', async () => {
await expect(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getIpfsId(123 as any)
).rejects.toThrow(/ArrayBufferView/);
});
});
71 changes: 71 additions & 0 deletions packages/lit-client/src/ipfs/getIpfsId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as Hash from 'typestub-ipfs-only-hash';

export type IpfsCidV0 = `Qm${string}`;

type SupportedInput = string | Uint8Array | ArrayBuffer | ArrayBufferView;

// Ensure string inputs are encoded without relying on Node's global Buffer, falling back to util.TextEncoder when needed.
const encodeString = (value: string): Uint8Array => {
if (typeof TextEncoder !== 'undefined') {
return new TextEncoder().encode(value);
}

try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { TextEncoder: NodeTextEncoder } = require('util');
return new NodeTextEncoder().encode(value);
} catch (error) {
throw new Error('TextEncoder is not available in this environment');
}
};

const toUint8Array = (value: ArrayBuffer | ArrayBufferView): Uint8Array => {
// TypedArray/DataView instances expose a shared buffer; slice the relevant window into a standalone Uint8Array.
if (ArrayBuffer.isView(value)) {
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
}

return new Uint8Array(value);
};

const normalizeInput = (input: SupportedInput): Uint8Array => {
// Accommodate all portable input shapes while keeping the helper tree-shakeable and browser-friendly.
if (typeof input === 'string') {
return toUint8Array(encodeString(input));
}

if (input instanceof Uint8Array) {
return toUint8Array(input);
}

if (typeof ArrayBuffer !== 'undefined') {
if (input instanceof ArrayBuffer) {
return toUint8Array(input);
}

if (ArrayBuffer.isView(input)) {
return toUint8Array(input);
}
}

throw new TypeError(
'Input must be provided as a string, Uint8Array, ArrayBuffer or ArrayBufferView'
);
};

/**
* Generate a CIDv0 IPFS identifier for the provided content.
*/
export const getIpfsId = async (input: SupportedInput): Promise<IpfsCidV0> => {
const normalizedInput = normalizeInput(input);
const hashOf = Hash.of as unknown as (
value: string | Uint8Array
) => Promise<string>;
const cid = await hashOf(normalizedInput);

if (!cid.startsWith('Qm')) {
throw new Error('Generated IPFS CID is not CIDv0');
}

return cid as IpfsCidV0;
};
2 changes: 2 additions & 0 deletions packages/lit-client/src/ipfs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { getIpfsId } from './getIpfsId';
export type { IpfsCidV0 } from './getIpfsId';
Loading
Loading