UNPKG

@nervosnetwork/ckb-sdk-utils

Version:

Utils module of @nervosnetwork/ckb-sdk-core

229 lines 10.1 kB
"use strict"; 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