sensible-sdk
Version:
Sensible-SDK
261 lines (260 loc) • 11.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getQuerySensibleID = exports.getQueryGenesis = exports.getQueryCodehash = exports.updateScript = exports.parseDataPart = exports.newDataPart = exports.getNewTokenScript = exports.getDataPart = exports.getContractCodeHash = exports.getContractCode = exports.getTokenName = exports.getTokenSymbol = exports.getGenesisFlag = exports.getDecimalNum = exports.getTokenAddress = exports.getGenesisHash = exports.getRabinPubKeyHashArrayHash = exports.getSensibleID = exports.getTokenID = exports.getTokenAmount = exports.getHeaderLen = exports.GENESIS_FLAG = exports.FT_OP_TYPE = exports.OP_UNLOCK_FROM_CONTRACT = exports.OP_TRANSFER = exports.nonGenesisFlag = exports.EMPTY_ADDRESS = exports.GENESIS_TOKEN_ID = exports.SIGNER_VERIFY_NUM = exports.SIGNER_NUM = exports.PROTO_VERSION = void 0;
const BN = require("../../bn.js");
const bsv = require("../../bsv");
const proto = require("../../common/protoheader");
const Utils = require("../../common/utils");
const scryptlib_1 = require("../../scryptlib");
exports.PROTO_VERSION = 1;
exports.SIGNER_NUM = 5;
exports.SIGNER_VERIFY_NUM = 3;
// token specific
//<type specific data> = <token_name (20 bytes)> + <token_symbol (10 bytes)> + <is_genesis(1 byte)> + <decimal_num(1 byte)> + <public key hash(20 bytes)> + <token value(8 bytes)> + <tokenid(36 bytes)> + <proto header>
const TOKEN_ID_LEN = 20;
const SENSIBLE_ID_LEN = 36;
const RABIN_PUBKEY_HASH_ARRAY_HASH_LEN = 20;
const GENESIS_HASH_LEN = 20;
const TOKEN_AMOUNT_LEN = 8;
const TOKEN_ADDRESS_LEN = 20;
const DECIMAL_NUM_LEN = 1;
const GENESIS_FLAG_LEN = 1;
const TOKEN_SYMBOL_LEN = 10;
const TOKEN_NAME_LEN = 20;
const SENSIBLE_ID_OFFSET = SENSIBLE_ID_LEN + proto.getHeaderLen();
const RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET = SENSIBLE_ID_OFFSET + RABIN_PUBKEY_HASH_ARRAY_HASH_LEN;
const GENESIS_HASH_OFFSET = RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET + GENESIS_HASH_LEN;
const TOKEN_AMOUNT_OFFSET = GENESIS_HASH_OFFSET + TOKEN_AMOUNT_LEN;
const TOKEN_ADDRESS_OFFSET = TOKEN_AMOUNT_OFFSET + TOKEN_ADDRESS_LEN;
const DECIMAL_NUM_OFFSET = TOKEN_ADDRESS_OFFSET + DECIMAL_NUM_LEN;
const GENESIS_FLAG_OFFSET = DECIMAL_NUM_OFFSET + GENESIS_FLAG_LEN;
const TOKEN_SYMBOL_OFFSET = GENESIS_FLAG_OFFSET + TOKEN_SYMBOL_LEN;
const TOKEN_NAME_OFFSET = TOKEN_SYMBOL_OFFSET + TOKEN_NAME_LEN;
const TOKEN_HEADER_LEN = TOKEN_NAME_OFFSET;
exports.GENESIS_TOKEN_ID = Buffer.alloc(TOKEN_ID_LEN, 0);
exports.EMPTY_ADDRESS = Buffer.alloc(TOKEN_ADDRESS_LEN, 0);
exports.nonGenesisFlag = Buffer.alloc(1, 0);
exports.OP_TRANSFER = 1;
exports.OP_UNLOCK_FROM_CONTRACT = 2;
var FT_OP_TYPE;
(function (FT_OP_TYPE) {
FT_OP_TYPE[FT_OP_TYPE["TRANSFER"] = 1] = "TRANSFER";
FT_OP_TYPE[FT_OP_TYPE["UNLOCK_FROM_CONTRACT"] = 2] = "UNLOCK_FROM_CONTRACT";
})(FT_OP_TYPE = exports.FT_OP_TYPE || (exports.FT_OP_TYPE = {}));
var GENESIS_FLAG;
(function (GENESIS_FLAG) {
GENESIS_FLAG[GENESIS_FLAG["FALSE"] = 0] = "FALSE";
GENESIS_FLAG[GENESIS_FLAG["TRUE"] = 1] = "TRUE";
})(GENESIS_FLAG = exports.GENESIS_FLAG || (exports.GENESIS_FLAG = {}));
function getHeaderLen() {
return TOKEN_HEADER_LEN;
}
exports.getHeaderLen = getHeaderLen;
function getTokenAmount(script) {
if (script.length < TOKEN_AMOUNT_OFFSET)
return BN.Zero;
return BN.fromBuffer(script.slice(script.length - TOKEN_AMOUNT_OFFSET, script.length - TOKEN_AMOUNT_OFFSET + TOKEN_AMOUNT_LEN), { endian: "little" });
}
exports.getTokenAmount = getTokenAmount;
function getTokenID(script) {
return bsv.crypto.Hash.sha256ripemd160(script.slice(script.length - GENESIS_HASH_OFFSET, script.length - proto.getHeaderLen()));
}
exports.getTokenID = getTokenID;
function getSensibleID(script0) {
if (script0.length < SENSIBLE_ID_OFFSET)
return { txid: "", index: 0 };
let script = Buffer.from(script0);
let sensibleIDBuf = script.slice(script.length - SENSIBLE_ID_OFFSET, script.length - SENSIBLE_ID_OFFSET + SENSIBLE_ID_LEN);
let txid = sensibleIDBuf.slice(0, 32).reverse().toString("hex"); //reverse会改变原对象
let index = sensibleIDBuf.readUIntLE(32, 4);
let sensibleID = { txid, index };
return sensibleID;
}
exports.getSensibleID = getSensibleID;
function getRabinPubKeyHashArrayHash(script) {
return script
.slice(script.length - RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET, script.length -
RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET +
RABIN_PUBKEY_HASH_ARRAY_HASH_LEN)
.toString("hex");
}
exports.getRabinPubKeyHashArrayHash = getRabinPubKeyHashArrayHash;
function getGenesisHash(script) {
return script
.slice(script.length - GENESIS_HASH_OFFSET, script.length - GENESIS_HASH_OFFSET + GENESIS_HASH_LEN)
.toString("hex");
}
exports.getGenesisHash = getGenesisHash;
function getTokenAddress(script) {
if (script.length < TOKEN_ADDRESS_OFFSET)
return "";
return script
.slice(script.length - TOKEN_ADDRESS_OFFSET, script.length - TOKEN_ADDRESS_OFFSET + TOKEN_ADDRESS_LEN)
.toString("hex");
}
exports.getTokenAddress = getTokenAddress;
function getDecimalNum(script) {
if (script.length < DECIMAL_NUM_OFFSET)
return 0;
return script.readUIntLE(script.length - DECIMAL_NUM_OFFSET, DECIMAL_NUM_LEN);
}
exports.getDecimalNum = getDecimalNum;
function getGenesisFlag(script) {
if (script.length < GENESIS_FLAG_OFFSET)
return 0;
return script.readUIntLE(script.length - GENESIS_FLAG_OFFSET, GENESIS_FLAG_LEN);
}
exports.getGenesisFlag = getGenesisFlag;
function getTokenSymbol(script) {
if (script.length < TOKEN_SYMBOL_OFFSET)
return "";
let buf = script.slice(script.length - TOKEN_SYMBOL_OFFSET, script.length - TOKEN_SYMBOL_OFFSET + TOKEN_SYMBOL_LEN);
return buf.toString();
}
exports.getTokenSymbol = getTokenSymbol;
function getTokenName(script) {
if (script.length < TOKEN_NAME_OFFSET)
return "";
let buf = script.slice(script.length - TOKEN_NAME_OFFSET, script.length - TOKEN_NAME_OFFSET + TOKEN_NAME_LEN);
return buf.toString();
}
exports.getTokenName = getTokenName;
function getContractCode(script) {
return script.slice(0, script.length -
TOKEN_HEADER_LEN -
Utils.getVarPushdataHeader(TOKEN_HEADER_LEN).length);
}
exports.getContractCode = getContractCode;
function getContractCodeHash(script) {
return bsv.crypto.Hash.sha256ripemd160(getContractCode(script));
}
exports.getContractCodeHash = getContractCodeHash;
function getDataPart(script) {
return script.slice(script.length - TOKEN_HEADER_LEN, script.length);
}
exports.getDataPart = getDataPart;
function getNewTokenScript(scriptBuf, address, tokenAmount) {
const amountBuf = tokenAmount.toBuffer({ endian: "little", size: 8 });
const firstBuf = scriptBuf.slice(0, scriptBuf.length - TOKEN_ADDRESS_OFFSET);
const newScript = Buffer.concat([
firstBuf,
address,
amountBuf,
scriptBuf.slice(scriptBuf.length - GENESIS_HASH_OFFSET, scriptBuf.length),
]);
return newScript;
}
exports.getNewTokenScript = getNewTokenScript;
function newDataPart({ tokenName, tokenSymbol, genesisFlag, decimalNum, tokenAddress, tokenAmount, genesisHash, rabinPubKeyHashArrayHash, sensibleID, protoVersion, protoType, }) {
const tokenNameBuf = Buffer.alloc(TOKEN_NAME_LEN, 0);
if (tokenName) {
tokenNameBuf.write(tokenName);
}
const tokenSymbolBuf = Buffer.alloc(TOKEN_SYMBOL_LEN, 0);
if (tokenSymbol) {
tokenSymbolBuf.write(tokenSymbol);
}
const decimalBuf = Buffer.alloc(DECIMAL_NUM_LEN, 0);
if (decimalNum) {
decimalBuf.writeUInt8(decimalNum);
}
const genesisFlagBuf = Buffer.alloc(GENESIS_FLAG_LEN, 0);
if (genesisFlag) {
genesisFlagBuf.writeUInt8(genesisFlag);
}
const tokenAddressBuf = Buffer.alloc(TOKEN_ADDRESS_LEN, 0);
if (tokenAddress) {
tokenAddressBuf.write(tokenAddress, "hex");
}
let tokenAmountBuf = Buffer.alloc(TOKEN_AMOUNT_LEN, 0);
if (tokenAmount) {
tokenAmountBuf = tokenAmount
.toBuffer({ endian: "little", size: TOKEN_AMOUNT_LEN })
.slice(0, TOKEN_AMOUNT_LEN);
}
const genesisHashBuf = Buffer.alloc(GENESIS_HASH_LEN, 0);
if (genesisHash) {
genesisHashBuf.write(genesisHash, "hex");
}
const rabinPubKeyHashArrayHashBuf = Buffer.alloc(RABIN_PUBKEY_HASH_ARRAY_HASH_LEN, 0);
if (rabinPubKeyHashArrayHash) {
rabinPubKeyHashArrayHashBuf.write(rabinPubKeyHashArrayHash, "hex");
}
let sensibleIDBuf = Buffer.alloc(SENSIBLE_ID_LEN, 0);
if (sensibleID) {
const txidBuf = Buffer.from(sensibleID.txid, "hex").reverse();
const indexBuf = Buffer.alloc(4, 0);
indexBuf.writeUInt32LE(sensibleID.index);
sensibleIDBuf = Buffer.concat([txidBuf, indexBuf]);
}
const protoTypeBuf = Buffer.alloc(proto.PROTO_TYPE_LEN, 0);
if (protoType) {
protoTypeBuf.writeUInt32LE(protoType);
}
const protoVersionBuf = Buffer.alloc(proto.PROTO_VERSION_LEN);
if (protoVersion) {
protoVersionBuf.writeUInt32LE(protoVersion);
}
return Buffer.concat([
tokenNameBuf,
tokenSymbolBuf,
genesisFlagBuf,
decimalBuf,
tokenAddressBuf,
tokenAmountBuf,
genesisHashBuf,
rabinPubKeyHashArrayHashBuf,
sensibleIDBuf,
protoVersionBuf,
protoTypeBuf,
proto.PROTO_FLAG,
]);
}
exports.newDataPart = newDataPart;
function parseDataPart(scriptBuf) {
let tokenName = getTokenName(scriptBuf);
let tokenSymbol = getTokenSymbol(scriptBuf);
let decimalNum = getDecimalNum(scriptBuf);
let genesisFlag = getGenesisFlag(scriptBuf);
let tokenAddress = getTokenAddress(scriptBuf);
let tokenAmount = getTokenAmount(scriptBuf);
let genesisHash = getGenesisHash(scriptBuf);
let rabinPubKeyHashArrayHash = getRabinPubKeyHashArrayHash(scriptBuf);
let sensibleID = getSensibleID(scriptBuf);
let protoVersion = proto.getProtoVersioin(scriptBuf);
let protoType = proto.getProtoType(scriptBuf);
return {
tokenName,
tokenSymbol,
decimalNum,
genesisFlag,
tokenAddress,
tokenAmount,
genesisHash,
rabinPubKeyHashArrayHash,
sensibleID,
protoVersion,
protoType,
};
}
exports.parseDataPart = parseDataPart;
function updateScript(scriptBuf, dataPartObj) {
const firstBuf = scriptBuf.slice(0, scriptBuf.length - TOKEN_HEADER_LEN);
const dataPart = newDataPart(dataPartObj);
return Buffer.concat([firstBuf, dataPart]);
}
exports.updateScript = updateScript;
function getQueryCodehash(script) {
return (0, scryptlib_1.toHex)(getContractCodeHash(script));
}
exports.getQueryCodehash = getQueryCodehash;
function getQueryGenesis(script) {
return (0, scryptlib_1.toHex)(getTokenID(script));
}
exports.getQueryGenesis = getQueryGenesis;
function getQuerySensibleID(script0) {
let script = Buffer.from(script0);
let sensibleIDBuf = script.slice(script.length - SENSIBLE_ID_OFFSET, script.length - SENSIBLE_ID_OFFSET + SENSIBLE_ID_LEN);
return (0, scryptlib_1.toHex)(sensibleIDBuf);
}
exports.getQuerySensibleID = getQuerySensibleID;