@ckb-ccc/core
Version:
Core of CCC - CKBer's Codebase
148 lines (147 loc) • 5.18 kB
JavaScript
import { bech32, bech32m } from "bech32";
import { Script, hashTypeFromBytes } from "../ckb/index.js";
import { KnownScript } from "../client/index.js";
import { hexFrom } from "../hex/index.js";
/**
* Parses an address string into an address information object.
*
* @param address - The address string to parse.
* @returns An object containing the address prefix, address format, and payload array.
*
* @throws Will throw an error if the address format is unknown.
*
* @example
* ```typescript
* const addressInfo = addressPayloadFromString("ckt1112139193129");
* console.log(addressInfo.prefix); // Outputs the address prefix
* console.log(addressInfo.format); // Outputs the address format
* console.log(addressInfo.payload); // Outputs the payload array
* ```
*/
export function addressPayloadFromString(address) {
// Try parse full format address
try {
const { words, prefix } = bech32m.decode(address, ADDRESS_BECH32_LIMIT);
const decoded = bech32m.fromWords(words);
const formatType = decoded[0];
const payload = decoded.slice(1);
if (formatType === AddressFormat.Full) {
return { prefix, format: AddressFormat.Full, payload };
}
}
catch (_) { }
// Try parse legacy 2019 format address
try {
const { prefix, words } = bech32.decode(address, ADDRESS_BECH32_LIMIT);
const decoded = bech32.fromWords(words);
const formatType = decoded[0];
const payload = decoded.slice(1);
if ([
AddressFormat.FullData,
AddressFormat.FullType,
AddressFormat.Short,
].includes(formatType)) {
return { prefix, format: formatType, payload };
}
}
catch (_) { }
throw Error(`Unknown address format ${address}`);
}
/**
* Converts an address payload into an address-like object.
*
* @param prefix - The address prefix.
* @param format - The format of the address, as defined by the AddressFormat enum.
* @param payload - The payload array containing the address data.
* @param client - The client instance used to fetch known scripts.
* @returns A promise that resolves to an AddressLike object.
*
* @throws Will throw an error if the payload length is insufficient or if the script type is unknown.
*
* @example
* ```typescript
* const address = await addressFromPayload("ckt", AddressFormat.Full, [/* payload data *\/], client);
* console.log(address.script); // Outputs the script object
* console.log(address.prefix); // Outputs the address prefix
* ```
*/
export async function addressFromPayload(prefix, format, payload, client) {
if (format === AddressFormat.Full) {
if (payload.length < 32 + 1) {
throw new Error(`Invalid full address without enough payload ${hexFrom(payload)}`);
}
return {
script: {
codeHash: payload.slice(0, 32),
hashType: hashTypeFromBytes(payload.slice(32, 33)),
args: payload.slice(33),
},
prefix,
};
}
if (format === AddressFormat.FullData) {
if (payload.length < 32) {
throw new Error(`Invalid full data address without enough payload ${hexFrom(payload)}`);
}
return {
script: {
codeHash: payload.slice(0, 32),
hashType: "data",
args: payload.slice(32),
},
prefix,
};
}
if (format === AddressFormat.FullType) {
if (payload.length < 32) {
throw new Error(`Invalid full type address without enough payload ${hexFrom(payload)}`);
}
return {
script: {
codeHash: payload.slice(0, 32),
hashType: "type",
args: payload.slice(32),
},
prefix,
};
}
// format === AddressFormat.Short
if (payload.length !== 21) {
throw new Error(`Invalid short address without enough payload ${hexFrom(payload)}`);
}
const script = [
KnownScript.Secp256k1Blake160,
KnownScript.Secp256k1Multisig,
KnownScript.AnyoneCanPay,
][payload[0]];
if (script === undefined) {
throw new Error(`Invalid short address with unknown script ${hexFrom(payload)}`);
}
return {
script: await Script.fromKnownScript(client, script, payload.slice(1)),
prefix,
};
}
export var AddressFormat;
(function (AddressFormat) {
/**
* full version identifies the hashType
*/
AddressFormat[AddressFormat["Full"] = 0] = "Full";
/**
* @deprecated
* short version for locks with Known codeHash, deprecated
*/
AddressFormat[AddressFormat["Short"] = 1] = "Short";
/**
* @deprecated
* full version with hashType = "Data", deprecated
*/
AddressFormat[AddressFormat["FullData"] = 2] = "FullData";
/**
* @deprecated
* full version with hashType = "Type", deprecated
*/
AddressFormat[AddressFormat["FullType"] = 4] = "FullType";
})(AddressFormat || (AddressFormat = {}));
export const ADDRESS_BECH32_LIMIT = 1023;