@dolr-ai/identity
v0.1.4
Published
TypeScript implementation of yral-identity for authenticating with Dolr off-chain services
Maintainers
Readme
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:
- Basic functionality with Ed25519KeyIdentity
- JSON serialization compatibility with the Rust implementation
- Proper Candid encoding of arguments
- Delegation support and serialization
Run the tests with:
npm testAPI 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 messagemethodName: string- The name of the method to callargs: Uint8Array- The encoded Candid argumentssender: Principal- The Principal of the message senderingressExpiry: Expiry- When the message expiresnonce?: Uint8Array- Optional nonce for replay protectioningressMaxAgeMs: number- The maximum age of the message in milliseconds
Methods
withCanisterId(canisterId: Principal): Message- Sets the canister IDwithMethodName(methodName: string): Message- Sets the method namewithArgs(argTypes: IDL.Type[], args: unknown[]): Message- Sets and encodes the arguments as CandidwithIngressMaxAge(maxAgeMs: number): Message- Sets how long the message is validwithNonce(nonce: Uint8Array): Message- Sets a nonce for the messagetoCallRequest(): 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 bytespublic_key?: Uint8Array- The public key bytes of the signeringress_expiry: Expiry- When the signature expiresdelegations?: SignedDelegation[]- Optional delegations for delegation signingsender: Principal- The Principal of the signer
Methods
static fromAgentSignature(signature: AgentSignature, ingressExpiry: Expiry, sender: Principal): Signature- Converts from agent signature formatserializeJSON(): 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:
- Sets the sender in the message to the identity's principal
- Creates a CallRequest from the message
- Calculates the request ID
- Signs the request ID using the provided identity
- Extracts the signature and public key
- 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
