ton3-core
Version:
TON low-level API tools
167 lines • 5.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Address = void 0;
const checksum_1 = require("./utils/checksum");
const helpers_1 = require("./utils/helpers");
const FLAG_BOUNCEABLE = 0x11;
const FLAG_NON_BOUNCEABLE = 0x51;
const FLAG_TEST_ONLY = 0x80;
class Address {
constructor(address, options) {
const isAddress = Address.isAddress(address);
const isEncoded = Address.isEncoded(address);
const isRaw = Address.isRaw(address);
let result;
switch (true) {
case isAddress:
result = Address.parseAddress(address);
break;
case isEncoded:
result = Address.parseEncoded(address);
break;
case isRaw:
result = Address.parseRaw(address);
break;
default:
result = null;
break;
}
if (result === null) {
throw new Error('Address: can\'t parse address. Unknown type.');
}
const { workchain = result.workchain, bounceable = result.bounceable, testOnly = result.testOnly } = options || {};
this._hash = result.hash;
this._workchain = workchain;
this._bounceable = bounceable;
this._testOnly = testOnly;
}
get hash() {
return new Uint8Array(this._hash);
}
get workchain() {
return this._workchain;
}
get bounceable() {
return this._bounceable;
}
get testOnly() {
return this._testOnly;
}
static isEncoded(address) {
const re = /^([a-zA-Z0-9_-]{48}|[a-zA-Z0-9\/\+]{48})$/;
return typeof address === 'string' && re.test(address);
}
static isRaw(address) {
const re = /^-?[0-9]:[a-zA-Z0-9]{64}$/;
return typeof address === 'string' && re.test(address);
}
static parseEncoded(value) {
const base64 = value.replace(/-/g, '+').replace(/_/g, '/');
const bytes = (0, helpers_1.base64ToBytes)(base64);
const data = Array.from(bytes);
const address = data.splice(0, 34);
const checksum = data.splice(0, 2);
const crc = (0, checksum_1.crc16BytesBe)(address);
if (!(0, helpers_1.bytesCompare)(crc, checksum)) {
throw new Error('Address: can\'t parse address. Wrong checksum.');
}
const { buffer } = new Uint8Array(address.splice(0, 2));
const view = new DataView(buffer);
const tag = view.getUint8(0);
const workchain = view.getInt8(1);
const hash = new Uint8Array(address.splice(0, 32));
const { bounceable, testOnly } = Address.decodeTag(tag);
return {
bounceable,
testOnly,
workchain,
hash
};
}
static parseAddress(value) {
const { workchain, bounceable, testOnly } = value;
const hash = new Uint8Array(value.hash);
return {
bounceable,
testOnly,
workchain,
hash
};
}
static parseRaw(value) {
const data = value.split(':');
const workchain = parseInt(data[0], 10);
const hash = (0, helpers_1.hexToBytes)(data[1]);
const bounceable = false;
const testOnly = false;
return {
bounceable,
testOnly,
workchain,
hash
};
}
static encodeTag(options) {
const { bounceable, testOnly } = options;
const tag = bounceable ? FLAG_BOUNCEABLE : FLAG_NON_BOUNCEABLE;
return testOnly ? (tag | FLAG_TEST_ONLY) : tag;
}
static decodeTag(tag) {
let data = tag;
const testOnly = (data & FLAG_TEST_ONLY) !== 0;
if (testOnly) {
data ^= FLAG_TEST_ONLY;
}
if (![FLAG_BOUNCEABLE, FLAG_NON_BOUNCEABLE].includes(data)) {
throw new Error('Address: bad address tag.');
}
const bounceable = data === FLAG_BOUNCEABLE;
return {
bounceable,
testOnly
};
}
eq(address) {
return address === this || ((0, helpers_1.bytesCompare)(this._hash, address.hash) && this._workchain === address.workchain);
}
toString(type = 'base64', options) {
const { workchain = this.workchain, bounceable = this.bounceable, testOnly = this.testOnly, urlSafe = true } = options || {};
if (typeof workchain !== 'number' || workchain < -128 || workchain >= 128) {
throw new Error('Address: workchain must be int8.');
}
if (typeof bounceable !== 'boolean') {
throw new Error('Address: bounceable flag must be a boolean.');
}
if (typeof testOnly !== 'boolean') {
throw new Error('Address: testOnly flag must be a boolean.');
}
if (typeof urlSafe !== 'boolean') {
throw new Error('Address: urlSafe flag must be a boolean.');
}
if (type === 'raw') {
return `${workchain}:${(0, helpers_1.bytesToHex)(this._hash)}`.toUpperCase();
}
const tag = Address.encodeTag({ bounceable, testOnly });
const address = new Uint8Array([tag, workchain, ...this._hash]);
const checksum = (0, checksum_1.crc16BytesBe)(address);
const base64 = (0, helpers_1.bytesToBase64)(new Uint8Array([...address, ...checksum]));
return urlSafe
? base64.replace(/\//g, '_').replace(/\+/g, '-')
: base64.replace(/_/g, '/').replace(/-/g, '+');
}
static isAddress(address) {
return address instanceof Address;
}
static isValid(address) {
try {
new Address(address);
return true;
}
catch (e) {
return false;
}
}
}
exports.Address = Address;
Address.NONE = null;
//# sourceMappingURL=address.js.map