Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/v0.0.1 alpha.183 #171

Merged
merged 2 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [0.0.1-alpha.183](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.182...v0.0.1-alpha.183) (2024-10-31)


### Features

* add base64 getters to udi class ([9b55e84](https://github.com/DIG-Network/dig-chia-sdk/commit/9b55e84a446894c11f2489043dd51d1e4ff73a9c))

### [0.0.1-alpha.182](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.181...v0.0.1-alpha.182) (2024-10-31)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dignetwork/dig-sdk",
"version": "0.0.1-alpha.182",
"version": "0.0.1-alpha.183",
"description": "",
"type": "commonjs",
"main": "./dist/index.js",
Expand Down
93 changes: 31 additions & 62 deletions src/utils/Udi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,92 +27,57 @@ class Udi {

static convertToBuffer(input: string | Buffer): Buffer {
if (Buffer.isBuffer(input)) {
if (input.length !== 32) {
throw new Error("Buffer must be exactly 32 bytes.");
}
return input;
}

if (Udi.isHex(input)) {
return Buffer.from(input, "hex");
// Attempt hex decoding
if (/^[a-fA-F0-9]+$/.test(input) && input.length === 64) {
try {
const buffer = Buffer.from(input, "hex");
if (buffer.length === 32) return buffer;
} catch (e) {
console.warn("Hex decoding failed, trying next encoding...");
}
}

if (Udi.isBase32(input)) {
// Attempt Base32 decoding
try {
const paddedInput = Udi.addBase32Padding(input.toUpperCase());
return Buffer.from(base32Decode(paddedInput, false));
const buffer = Buffer.from(base32Decode(paddedInput, false));
if (buffer.length === 32) return buffer;
} catch (e) {
console.warn("Base32 decoding failed, trying Base64 encoding...");
}

if (Udi.isBase64Safe(input)) {
// Attempt Base64 (URL-safe) decoding
try {
const standardBase64 = Udi.addBase64Padding(Udi.toStandardBase64(input));
return Buffer.from(standardBase64, "base64");
const buffer = Buffer.from(standardBase64, "base64");
if (buffer.length === 32) return buffer;
} catch (e) {
throw new Error("Invalid input encoding. Must be 32-byte hex, Base32, or Base64 string.");
}

throw new Error("Invalid input encoding. Must be 32-byte hex, Base32, or Base64 URL-safe string.");
}

static isHex(input: string): boolean {
return /^[a-fA-F0-9]{64}$/.test(input);
}

static isBase32(input: string): boolean {
return /^[a-z2-7]{52}$/.test(input.toLowerCase());
}

static isBase64Safe(input: string): boolean {
return /^[A-Za-z0-9\-_]+$/.test(input);
throw new Error("Failed to decode input as a 32-byte buffer.");
}

static addBase32Padding(input: string): string {
const paddingNeeded = (8 - (input.length % 8)) % 8;
return input + "=".repeat(paddingNeeded);
}

static toStandardBase64(base64Safe: string): string {
return base64Safe.replace(/-/g, "+").replace(/_/g, "/");
}

static toBase64Safe(base64Standard: string): string {
return base64Standard.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
static toStandardBase64(base64UrlSafe: string): string {
return base64UrlSafe.replace(/-/g, "+").replace(/_/g, "/");
}

static addBase64Padding(base64: string): string {
const paddingNeeded = (4 - (base64.length % 4)) % 4;
return base64 + "=".repeat(paddingNeeded);
}

withRootHash(rootHash: string | Buffer | null): Udi {
return new Udi(this.chainName, this._storeId, rootHash, this.resourceKey);
}

withResourceKey(resourceKey: string | null): Udi {
return new Udi(this.chainName, this._storeId, this._rootHash, resourceKey);
}

static fromUrn(urn: string): Udi {
const parsedUrn = urns.parseURN(urn);
if (parsedUrn.nid.toLowerCase() !== Udi.nid) {
throw new Error(`Invalid UDI: ${parsedUrn.nid}`);
}

const parts = parsedUrn.nss.split(":");
if (parts.length < 2) {
throw new Error(`Invalid UDI format: ${parsedUrn.nss}`);
}

const chainName = parts[0];
const storeId = parts[1].split("/")[0];

let rootHash: string | null = null;
if (parts.length > 2) {
rootHash = parts[2].split("/")[0];
}

const pathParts = parsedUrn.nss.split("/");
let resourceKey: string | null = null;
if (pathParts.length > 1) {
resourceKey = pathParts.slice(1).join("/");
}

return new Udi(chainName, storeId, rootHash, resourceKey);
}

toUrn(encoding: "hex" | "base32" | "base64" = "hex"): string {
const storeIdStr = this.bufferToString(this._storeId, encoding);
let urn = `${Udi.namespace}:${this.chainName}:${storeIdStr}`;
Expand All @@ -135,11 +100,15 @@ class Udi {
} else if (encoding === "base32") {
return base32Encode(buffer).toLowerCase().replace(/=+$/, "");
} else if (encoding === "base64") {
return Udi.toBase64Safe(buffer.toString("base64"));
return Udi.toBase64UrlSafe(buffer.toString("base64"));
}
throw new Error("Unsupported encoding type");
}

static toBase64UrlSafe(base64Standard: string): string {
return base64Standard.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

equals(other: Udi): boolean {
return (
this._storeId.equals(other._storeId) &&
Expand Down
Loading