@dolr-ai/identity
TypeScript icon, indicating that this package has built-in type declarations

0.1.4 • Public • Published

yral-identity-ts

A TypeScript implementation of the yral-identity library for authenticating with Yral off-chain services. This library provides a compatible way to sign messages with Internet Computer identities and produce signatures that are compatible with the Rust-based yral-identity library.

Usage

Basic Usage

import { Ed25519KeyIdentity } from "@dfinity/identity";
import { Principal } from "@dfinity/principal";
import { IDL } from "@dfinity/candid";
import { Message, signMessage } from "yral-identity-ts";

// Create or load an identity
const identity = Ed25519KeyIdentity.generate();

// Create a message
const canisterId = Principal.fromText("rrkah-fqaaa-aaaaa-aaaaq-cai");
const message = new Message()
  .withCanisterId(canisterId)
  .withMethodName("greet")
  .withArgs([IDL.Text], ["Hello, World!"])
  .withIngressMaxAge(300_000);

// Sign the message
const signature = await signMessage(identity, message);

// Convert to JSON for sending to the service
const signatureJson = signature.serializeJSON();

Using Delegations

The library supports delegations, which allow one identity to act on behalf of another:

import {
  DelegationChain,
  DelegationIdentity,
  Ed25519KeyIdentity,
} from "@dfinity/identity";
import { Principal } from "@dfinity/principal";
import { Message, signMessage } from "yral-identity-ts";
import { IDL } from "@dfinity/candid";

// Create identities
const identity = Ed25519KeyIdentity.generate();
const delegationIdentity = Ed25519KeyIdentity.generate();

// Create delegation chain
const delegation = await DelegationChain.create(
  identity,
  delegationIdentity.getPublicKey(),
);

// Create delegation identity
const delegatedIdentity = DelegationIdentity.fromDelegation(
  delegationIdentity,
  delegation,
);

// Create and sign a message with the delegated identity
const message = new Message()
  .withCanisterId(Principal.fromText("rrkah-fqaaa-aaaaa-aaaaq-cai"))
  .withMethodName("greet")
  .withArgs([IDL.Text], ["Hello, World!"])
  .withIngressMaxAge(300_000);

const signature = await signMessage(delegatedIdentity, message);

// This signature with delegations can now be serialized
const signatureJson = signature.serializeJSON();

Comprehensive Tests

The library includes tests that verify:

  1. Basic functionality with Ed25519KeyIdentity
  2. JSON serialization compatibility with the Rust implementation
  3. Proper Candid encoding of arguments
  4. Delegation support and serialization

Run the tests with:

npm test

API Reference

YralIdentityError

Error class for yral-identity-ts operations.

class YralIdentityError extends Error {
  static SenderNotFound: YralIdentityError;
  static Signing(e: Error): YralIdentityError;
  static ArgumentEncoding(e: Error): YralIdentityError;
}

Message

The Message class represents a message that can be signed and sent to a canister.

Constructor

constructor(
  canisterId: Principal = Principal.anonymous(),
  methodName: string = '',
  args: Uint8Array = new Uint8Array(),
  sender: Principal = Principal.anonymous(),
  ingressExpiry: number = 120_000,
  nonce?: Uint8Array
)

Properties

  • canisterId: Principal - The ID of the canister that will receive the message
  • methodName: string - The name of the method to call
  • args: Uint8Array - The encoded Candid arguments
  • sender: Principal - The Principal of the message sender
  • ingressExpiry: Expiry - When the message expires
  • nonce?: Uint8Array - Optional nonce for replay protection
  • ingressMaxAgeMs: number - The maximum age of the message in milliseconds

Methods

  • withCanisterId(canisterId: Principal): Message - Sets the canister ID
  • withMethodName(methodName: string): Message - Sets the method name
  • withArgs(argTypes: IDL.Type[], args: unknown[]): Message - Sets and encodes the arguments as Candid
  • withIngressMaxAge(maxAgeMs: number): Message - Sets how long the message is valid
  • withNonce(nonce: Uint8Array): Message - Sets a nonce for the message
  • toCallRequest(): CallRequest - Converts to a CallRequest for signing

Delegation Interface

interface Delegation {
  pubkey: Uint8Array; // Public key of the delegatee
  expiration_ns: bigint; // Expiration in nanoseconds since epoch
  targets?: Principal[]; // Optional target canisters for the delegation
}

SignedDelegation Interface

interface SignedDelegation {
  delegation: Delegation; // The delegation details
  signature: Uint8Array; // Signature from the delegator
}

Signature

The Signature class represents a signature that can be sent to a service for authentication.

Constructor

constructor(
  sig?: Uint8Array,
  publicKey?: Uint8Array,
  ingressExpiry: Expiry = new Expiry(120_000),
  sender: Principal = Principal.anonymous(),
  delegations?: SignedDelegation[]
)

Properties

  • sig?: Uint8Array - The signature bytes
  • public_key?: Uint8Array - The public key bytes of the signer
  • ingress_expiry: Expiry - When the signature expires
  • delegations?: SignedDelegation[] - Optional delegations for delegation signing
  • sender: Principal - The Principal of the signer

Methods

  • static fromAgentSignature(signature: AgentSignature, ingressExpiry: Expiry, sender: Principal): Signature - Converts from agent signature format
  • serializeJSON(): string - Converts the signature to a JSON string suitable for interoperability with Rust services

signMessage Function

async function signMessage(
  identity: DelegationIdentity | SignIdentity,
  message: Message,
): Promise<Signature>;

Signs a message using the provided identity. This function:

  1. Sets the sender in the message to the identity's principal
  2. Creates a CallRequest from the message
  3. Calculates the request ID
  4. Signs the request ID using the provided identity
  5. Extracts the signature and public key
  6. Creates and returns a Signature object

JSON Serialization

The Signature class includes a serializeJSON() method that ensures proper serialization of all properties including Uint8Array objects, which are converted to standard arrays. This is crucial for compatibility with the Rust implementation.

When using the serializeJSON() method on a Signature instance, the result will be properly formatted for use with yral-identity Rust services:

{
  "sig": [1, 2, 3, ...],
  "public_key": [4, 5, 6, ...],
  "ingress_expiry": {
    "secs": 120,
    "nanos": 0
  },
  "delegations": [
    {
      "delegation": {
        "pubkey": [7, 8, 9, ...],
        "expiration_ns": 3600000000000,
        "targets": ["aaaaa-aa"]
      },
      "signature": [10, 11, 12, ...]
    }
  ],
  "sender": "rrkah-fqaaa-aaaaa-aaaaq-cai"
}

License

MIT

Package Sidebar

Install

npm i @dolr-ai/identity

Weekly Downloads

4

Version

0.1.4

License

MIT

Unpacked Size

48.5 kB

Total Files

12

Last publish

Collaborators

  • hrsh-dolr