lotus-sdk
Version:
Central repository for several classes of tools for integrating with, and building for, the Lotusia ecosystem
164 lines (163 loc) • 4.93 kB
JavaScript
import { Address } from './address.js';
const DEFAULT_PREFIX = 'giveto:';
const URI_PREFIXES = [DEFAULT_PREFIX];
export class URI {
_address;
_amount;
_label;
_message;
_otherParams = {};
constructor(data, knownParams) {
if (typeof data === 'string') {
this._fromString(data, knownParams);
}
else if (typeof data === 'object') {
this._fromObject(data);
}
else {
throw new Error('Invalid URI data');
}
}
static fromString(data) {
return new URI(data);
}
static fromObject(data) {
return new URI(data);
}
static isValid(data, knownParams) {
try {
new URI(data, knownParams);
return true;
}
catch (e) {
return false;
}
}
_fromString(uriString, knownParams) {
const index = URI_PREFIXES.findIndex(prefix => uriString.startsWith(prefix));
if (index === -1) {
throw new Error('Invalid Lotus URI');
}
const prefix = URI_PREFIXES[index];
const uri = uriString.substring(prefix.length);
const parts = uri.split('?');
if (parts.length === 0) {
throw new Error('Invalid Lotus URI format');
}
const addressPart = parts[0];
if (addressPart) {
try {
this._address = Address.fromString(addressPart);
}
catch (e) {
throw new Error('Invalid Lotus address in URI');
}
}
if (parts.length > 1) {
const queryString = parts[1];
const params = new URLSearchParams(queryString);
for (const [key, value] of params) {
switch (key) {
case 'amount':
this._amount = parseFloat(value);
break;
case 'label':
this._label = decodeURIComponent(value);
break;
case 'message':
this._message = decodeURIComponent(value);
break;
default:
if (!knownParams || knownParams.includes(key)) {
this._otherParams[key] = decodeURIComponent(value);
}
break;
}
}
}
}
_fromObject(data) {
if (data.address) {
try {
this._address = Address.fromString(data.address);
}
catch (e) {
throw new Error('Invalid Lotus address');
}
}
if (data.amount !== undefined) {
this._amount = data.amount;
}
if (data.label) {
this._label = data.label;
}
if (data.message) {
this._message = data.message;
}
Object.keys(data).forEach(key => {
if (!['address', 'amount', 'label', 'message'].includes(key)) {
this._otherParams[key] = String(data[key]);
}
});
}
get address() {
return this._address;
}
get amount() {
return this._amount;
}
get label() {
return this._label;
}
get message() {
return this._message;
}
get otherParams() {
return { ...this._otherParams };
}
toString(prefix) {
if (!this._address) {
throw new Error('Cannot convert URI to string without address');
}
if (prefix && !URI_PREFIXES.includes(prefix)) {
throw new Error('Invalid URI prefix specified');
}
let uri = `${prefix ?? DEFAULT_PREFIX}${this._address.toString()}`;
const params = [];
if (this._amount !== undefined) {
params.push(`amount=${this._amount}`);
}
if (this._label) {
params.push(`label=${encodeURIComponent(this._label)}`);
}
if (this._message) {
params.push(`message=${encodeURIComponent(this._message)}`);
}
Object.keys(this._otherParams).forEach(key => {
params.push(`${key}=${encodeURIComponent(this._otherParams[key])}`);
});
if (params.length > 0) {
uri += '?' + params.join('&');
}
return uri;
}
toObject() {
const obj = {};
if (this._address) {
obj.address = this._address.toString();
}
if (this._amount !== undefined) {
obj.amount = this._amount;
}
if (this._label) {
obj.label = this._label;
}
if (this._message) {
obj.message = this._message;
}
Object.keys(this._otherParams).forEach(key => {
obj[key] = this._otherParams[key];
});
return obj;
}
}