@radixdlt/atom
Version:
Container for CRUD instructions known as 'Particles' that are sent to the Radix decentralized ledger
101 lines (88 loc) • 2.63 kB
text/typescript
import { ResourceIdentifierT } from './_types'
import { err, ok, Result } from 'neverthrow'
import { Address, AddressT } from '@radixdlt/account'
import {
DSONObjectEncoding,
JSONDecoding,
JSONEncoding,
serializerNotNeeded,
taggedStringDecoder,
} from '@radixdlt/data-formats'
import { Byte } from '@radixdlt/util'
const separator = '/'
const CBOR_BYTESTRING_PREFIX: Byte = 6
const JSON_TAG = ':rri:'
const JSONDecoder = taggedStringDecoder(JSON_TAG)((identifier: string) =>
fromString(identifier),
)
const jsonDecoding = JSONDecoding.withDecoders(
JSONDecoder,
).create<ResourceIdentifierT>()
const fromAddressAndName = (input: {
address: AddressT
name: string
}): ResourceIdentifierT => {
const address = input.address
const name = input.name
const identifier = ['', address.toString(), name].join(separator)
return {
...JSONEncoding(serializerNotNeeded)(() => `${JSON_TAG}${identifier}`),
...DSONObjectEncoding({
prefix: CBOR_BYTESTRING_PREFIX,
buffer: Buffer.from(identifier),
}),
address,
name,
toString: () => identifier,
equals: (other) => other.address.equals(address) && other.name === name,
}
}
const fromString = (
identifierString: string,
): Result<ResourceIdentifierT, Error> => {
const components = identifierString.split(separator)
if (components.length !== 3) return err(new Error('Invalid RRI string'))
if (components[0].length !== 0) return err(new Error('Expected leading /'))
const name = components[2]
if (name.length === 0) return err(new Error('Expected non empty name'))
return Address.fromBase58String(components[1]).map(
(address): ResourceIdentifierT => ({
...JSONEncoding(serializerNotNeeded)(
() => `${JSON_TAG}${identifierString}`,
),
...DSONObjectEncoding({
prefix: CBOR_BYTESTRING_PREFIX,
buffer: Buffer.from(identifierString),
}),
address,
name,
toString: () => identifierString,
equals: (other) =>
other.address.equals(address) && other.name === name,
}),
)
}
export const isResourceIdentifier = (
something: ResourceIdentifierT | unknown,
): something is ResourceIdentifierT => {
const inspection = something as ResourceIdentifierT
return (
inspection.address !== undefined &&
inspection.name !== undefined &&
inspection.toString !== undefined &&
inspection.equals !== undefined
)
}
const fromUnsafe = (
input: ResourceIdentifierT | string,
): Result<ResourceIdentifierT, Error> => {
return isResourceIdentifier(input) ? ok(input) : fromString(input)
}
export const ResourceIdentifier = {
JSON_TAG,
JSONDecoder,
...jsonDecoding,
fromAddressAndName,
fromUnsafe,
fromString,
}