@nervosnetwork/ckb-sdk-utils
Version:
Utils module of @nervosnetwork/ckb-sdk-core
229 lines • 10.1 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.addressToScript = exports.parseAddress = exports.pubkeyToAddress = exports.fullPayloadToAddress = exports.bech32Address = exports.toAddressPayload = exports.scriptToAddress = exports.Bech32Type = exports.AddressType = exports.AddressPrefix = void 0;
const index_js_1 = require("../index.js");
const systemScripts_js_1 = require("../systemScripts.js");
const index_js_2 = require("../convertors/index.js");
const index_js_3 = require("../exceptions/index.js");
const MAX_BECH32_LIMIT = 1023;
var AddressPrefix;
(function (AddressPrefix) {
AddressPrefix["Mainnet"] = "ckb";
AddressPrefix["Testnet"] = "ckt";
})(AddressPrefix = exports.AddressPrefix || (exports.AddressPrefix = {}));
var AddressType;
(function (AddressType) {
AddressType["FullVersion"] = "0x00";
AddressType["HashIdx"] = "0x01";
AddressType["DataCodeHash"] = "0x02";
AddressType["TypeCodeHash"] = "0x04";
})(AddressType = exports.AddressType || (exports.AddressType = {}));
var Bech32Type;
(function (Bech32Type) {
Bech32Type["Bech32"] = "bech32";
Bech32Type["Bech32m"] = "bech32m";
})(Bech32Type = exports.Bech32Type || (exports.Bech32Type = {}));
const payloadToAddress = (payload, isMainnet = true) => index_js_1.bech32m.encode(isMainnet ? AddressPrefix.Mainnet : AddressPrefix.Testnet, index_js_1.bech32m.toWords(payload), MAX_BECH32_LIMIT);
const scriptToPayload = ({ codeHash, hashType, args }) => {
if (!args.startsWith('0x')) {
throw new index_js_3.HexStringWithout0xException(args);
}
if (!codeHash.startsWith('0x') || codeHash.length !== 66) {
throw new index_js_3.CodeHashException(codeHash);
}
let HashType;
(function (HashType) {
HashType["data"] = "00";
HashType["type"] = "01";
HashType["data1"] = "02";
HashType["data2"] = "04";
})(HashType || (HashType = {}));
if (!HashType[hashType]) {
throw new index_js_3.HashTypeException(hashType);
}
return (0, index_js_2.hexToBytes)(`0x00${codeHash.slice(2)}${HashType[hashType]}${args.slice(2)}`);
};
const scriptToAddress = (script, isMainnet = true) => payloadToAddress(scriptToPayload(script), isMainnet);
exports.scriptToAddress = scriptToAddress;
const toAddressPayload = (args, type = AddressType.HashIdx, codeHashOrCodeHashIndex, hashType) => {
if (typeof args === 'string' && !args.startsWith('0x')) {
throw new index_js_3.HexStringWithout0xException(args);
}
if (![AddressType.HashIdx, AddressType.DataCodeHash, AddressType.TypeCodeHash, AddressType.FullVersion].includes(type)) {
throw new index_js_3.AddressFormatTypeException(+type);
}
if ([AddressType.DataCodeHash, AddressType.TypeCodeHash].includes(type)) {
console.warn(`Address of 'AddressType.DataCodeHash' or 'AddressType.TypeCodeHash' is deprecated, please use address of AddressPrefix.FullVersion`);
}
if (!codeHashOrCodeHashIndex) {
codeHashOrCodeHashIndex = type === AddressType.HashIdx ? '0x00' : systemScripts_js_1.SECP256K1_BLAKE160.codeHash;
}
if (type !== AddressType.FullVersion) {
return new Uint8Array([
...(0, index_js_2.hexToBytes)(type),
...(0, index_js_2.hexToBytes)(codeHashOrCodeHashIndex),
...(typeof args === 'string' ? (0, index_js_2.hexToBytes)(args) : args),
]);
}
if (!hashType && codeHashOrCodeHashIndex === systemScripts_js_1.SECP256K1_BLAKE160.codeHash) {
hashType = systemScripts_js_1.SECP256K1_BLAKE160.hashType;
}
if (!codeHashOrCodeHashIndex.startsWith('0x') || codeHashOrCodeHashIndex.length !== 66) {
throw new index_js_3.CodeHashException(codeHashOrCodeHashIndex);
}
if (!hashType) {
throw new index_js_3.ParameterRequiredException('hashType');
}
return scriptToPayload({
codeHash: codeHashOrCodeHashIndex,
hashType,
args: typeof args === 'string' ? args : (0, index_js_2.bytesToHex)(args),
});
};
exports.toAddressPayload = toAddressPayload;
const bech32Address = (args, { prefix = AddressPrefix.Mainnet, type = AddressType.HashIdx, codeHashOrCodeHashIndex = '' } = {}) => index_js_1.bech32.encode(prefix, index_js_1.bech32.toWords((0, exports.toAddressPayload)(args, type, codeHashOrCodeHashIndex)), MAX_BECH32_LIMIT);
exports.bech32Address = bech32Address;
const fullPayloadToAddress = ({ args, prefix, type = AddressType.DataCodeHash, codeHash, }) => (0, exports.bech32Address)(args, { prefix, type, codeHashOrCodeHashIndex: codeHash });
exports.fullPayloadToAddress = fullPayloadToAddress;
const pubkeyToAddress = (pubkey, options = {}) => {
const publicKeyHash = (0, index_js_1.blake160)(pubkey);
return (0, exports.bech32Address)(publicKeyHash, options);
};
exports.pubkeyToAddress = pubkeyToAddress;
const isValidShortVersionPayload = (payload, bech32Type) => {
const [type, index, ...data] = payload;
if (bech32Type !== Bech32Type.Bech32) {
throw new index_js_3.AddressFormatTypeAndEncodeMethodNotMatchException(type, bech32Type);
}
switch (index) {
case 0:
case 1: {
if (data.length !== 20) {
throw new index_js_3.AddressPayloadException(payload, 'short');
}
break;
}
case 2: {
if (data.length === 20 || data.length === 22 || data.length === 24) {
break;
}
throw new index_js_3.AddressPayloadException(payload, 'short');
}
default: {
throw new index_js_3.AddressPayloadException(payload, 'short');
}
}
};
const isPayloadValid = (payload, bech32Type) => {
const type = payload[0];
const data = payload.slice(1);
switch (type) {
case +AddressType.HashIdx: {
isValidShortVersionPayload(payload, bech32Type);
break;
}
case +AddressType.DataCodeHash:
case +AddressType.TypeCodeHash: {
if (bech32Type !== Bech32Type.Bech32) {
throw new index_js_3.AddressFormatTypeAndEncodeMethodNotMatchException(type, bech32Type);
}
if (data.length < 32) {
throw new index_js_3.AddressPayloadException(payload, 'full');
}
break;
}
case +AddressType.FullVersion: {
if (bech32Type !== Bech32Type.Bech32m) {
throw new index_js_3.AddressFormatTypeAndEncodeMethodNotMatchException(type, bech32Type);
}
const codeHash = data.slice(0, 32);
if (codeHash.length < 32) {
throw new index_js_3.CodeHashException((0, index_js_2.bytesToHex)(codeHash));
}
const hashType = parseInt(data[32].toString(), 16);
if (!Object.values(AddressType)
.map(i => +i)
.includes(hashType)) {
throw new index_js_3.HashTypeException(`0x${hashType.toString(16)}`);
}
break;
}
default: {
throw new index_js_3.AddressPayloadException(payload);
}
}
};
const parseAddress = (address, encode = 'binary') => {
let bech32Type;
let payload = new Uint8Array();
try {
const decoded = index_js_1.bech32.decode(address, MAX_BECH32_LIMIT);
bech32Type = Bech32Type.Bech32;
payload = new Uint8Array(index_js_1.bech32.fromWords(new Uint8Array(decoded.words)));
}
catch (_a) {
const decoded = index_js_1.bech32m.decode(address, MAX_BECH32_LIMIT);
bech32Type = Bech32Type.Bech32m;
payload = new Uint8Array(index_js_1.bech32m.fromWords(new Uint8Array(decoded.words)));
}
try {
isPayloadValid(payload, bech32Type);
}
catch (err) {
if (err instanceof index_js_3.AddressFormatTypeAndEncodeMethodNotMatchException) {
throw err;
}
throw new index_js_3.AddressException(address, err.stack, err.type);
}
return encode === 'binary' ? payload : (0, index_js_2.bytesToHex)(payload);
};
exports.parseAddress = parseAddress;
const addressToScript = (address) => {
const payload = (0, exports.parseAddress)(address);
const type = payload[0];
switch (type) {
case +AddressType.FullVersion: {
const HASH_TYPE = {
'00': 'data',
'01': 'type',
'02': 'data1',
'04': 'data2'
};
const p = (0, index_js_2.bytesToHex)(payload);
const codeHash = `0x${p.substr(4, 64)}`;
const hashType = HASH_TYPE[p.substr(68, 2)];
const args = `0x${p.substr(70)}`;
return { codeHash, hashType, args };
}
case +AddressType.HashIdx: {
const codeHashIndices = [
systemScripts_js_1.SECP256K1_BLAKE160,
systemScripts_js_1.SECP256K1_MULTISIG,
address.startsWith(AddressPrefix.Mainnet) ? systemScripts_js_1.ANYONE_CAN_PAY_MAINNET : systemScripts_js_1.ANYONE_CAN_PAY_TESTNET,
];
const index = payload[1];
const args = payload.slice(2);
const script = codeHashIndices[index];
return {
codeHash: script.codeHash,
hashType: script.hashType,
args: (0, index_js_2.bytesToHex)(args),
};
}
case +AddressType.DataCodeHash:
case +AddressType.TypeCodeHash: {
const codeHashAndArgs = (0, index_js_2.bytesToHex)(payload.slice(1));
const hashType = type === +AddressType.DataCodeHash ? 'data' : 'type';
return {
codeHash: codeHashAndArgs.substr(0, 66),
hashType,
args: `0x${codeHashAndArgs.substr(66)}`,
};
}
default: {
throw new index_js_3.AddressFormatTypeException(type);
}
}
};
exports.addressToScript = addressToScript;
//# sourceMappingURL=index.js.map
;