UNPKG

sensible-sdk

Version:

Sensible-SDK

231 lines (230 loc) 10.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getQuerySensibleID = exports.getQueryGenesis = exports.getQueryCodehash = exports.updateScript = exports.parseDataPart = exports.newDataPart = exports.getSensibleID = exports.getMetaidOutpoint = exports.getContractCodeHash = exports.getContractCode = exports.getGenesisFlag = exports.getNftAddress = exports.getTotalSupply = exports.getNftID = exports.getTokenIndex = exports.getGenesisHash = exports.getRabinPubKeyHashArrayHash = exports.EMPTY_ADDRESS = exports.GENESIS_TOKEN_ID = exports.GENESIS_FLAG = exports.PROTO_VERSION = exports.NFT_OP_TYPE = exports.SIGNER_VERIFY_NUM = exports.SIGNER_NUM = void 0; const bsv = require("../../bsv"); const proto = require("../../common/protoheader"); const Utils = require("../../common/utils"); const scryptlib_1 = require("../../scryptlib"); const BN = require("../../bn.js"); exports.SIGNER_NUM = 5; exports.SIGNER_VERIFY_NUM = 3; var NFT_OP_TYPE; (function (NFT_OP_TYPE) { NFT_OP_TYPE[NFT_OP_TYPE["TRANSFER"] = 1] = "TRANSFER"; NFT_OP_TYPE[NFT_OP_TYPE["UNLOCK_FROM_CONTRACT"] = 2] = "UNLOCK_FROM_CONTRACT"; })(NFT_OP_TYPE = exports.NFT_OP_TYPE || (exports.NFT_OP_TYPE = {})); exports.PROTO_VERSION = 1; 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 = {})); // <type specific data> + <proto header> // <proto header> = <type(4 bytes)> + <'sensible'(8 bytes)> //<nft type specific data> = <metaid_outpoint(36 bytes)> + <is_genesis(1 byte)> + <address(20 bytes)> + <totalSupply(8 bytes) + <tokenIndex(8 bytes)> + <genesisHash<20 bytes>) + <RABIN_PUBKEY_HASH_ARRAY_HASH(20 bytes)> + <sensibleID(36 bytes)> const SENSIBLE_ID_LEN = 36; const RABIN_PUBKEY_HASH_ARRAY_HASH_LEN = 20; const GENESIS_HASH_LEN = 20; const TOKEN_INDEX_LEN = 8; const NFT_ID_LEN = 20; const TOTAL_SUPPLY_LEN = 8; const NFT_ADDRESS_LEN = 20; const GENESIS_FLAG_LEN = 1; const METAID_OUTPOINT_LEN = 36; 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_INDEX_OFFSET = GENESIS_HASH_OFFSET + TOKEN_INDEX_LEN; const TOTAL_SUPPLY_OFFSET = TOKEN_INDEX_OFFSET + TOTAL_SUPPLY_LEN; const NFT_ADDRESS_OFFSET = TOTAL_SUPPLY_OFFSET + NFT_ADDRESS_LEN; const GENESIS_FLAG_OFFSET = NFT_ADDRESS_OFFSET + GENESIS_FLAG_LEN; const METAID_OUTPOINT_OFFSET = GENESIS_FLAG_OFFSET + METAID_OUTPOINT_LEN; const DATA_LEN = METAID_OUTPOINT_OFFSET; exports.GENESIS_TOKEN_ID = Buffer.alloc(NFT_ID_LEN, 0); exports.EMPTY_ADDRESS = Buffer.alloc(NFT_ADDRESS_LEN, 0); 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 getTokenIndex(script) { if (script.length < TOKEN_INDEX_OFFSET) return BN.Zero; return BN.fromBuffer(script.slice(script.length - TOKEN_INDEX_OFFSET, script.length - TOKEN_INDEX_OFFSET + TOKEN_INDEX_LEN), { endian: "little" }); } exports.getTokenIndex = getTokenIndex; function getNftID(script) { return bsv.crypto.Hash.sha256ripemd160(script.slice(script.length - TOKEN_INDEX_OFFSET, script.length - proto.getHeaderLen())); } exports.getNftID = getNftID; function getTotalSupply(script) { if (script.length < TOTAL_SUPPLY_OFFSET) return BN.Zero; return BN.fromBuffer(script.slice(script.length - TOTAL_SUPPLY_OFFSET, script.length - TOTAL_SUPPLY_OFFSET + TOTAL_SUPPLY_LEN), { endian: "little" }); } exports.getTotalSupply = getTotalSupply; function getNftAddress(script) { if (script.length < NFT_ADDRESS_OFFSET) return ""; return script .slice(script.length - NFT_ADDRESS_OFFSET, script.length - NFT_ADDRESS_OFFSET + NFT_ADDRESS_LEN) .toString("hex"); } exports.getNftAddress = getNftAddress; 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 getContractCode(script) { return script.slice(0, script.length - DATA_LEN - Utils.getVarPushdataHeader(DATA_LEN).length); } exports.getContractCode = getContractCode; function getContractCodeHash(script) { return bsv.crypto.Hash.sha256ripemd160(getContractCode(script)); } exports.getContractCodeHash = getContractCodeHash; function getMetaidOutpoint(script0) { if (script0.length < METAID_OUTPOINT_OFFSET) return { txid: "", index: 0 }; let script = Buffer.from(script0); let metaidOutpointBuf = script.slice(script.length - METAID_OUTPOINT_OFFSET, script.length - METAID_OUTPOINT_OFFSET + METAID_OUTPOINT_LEN); let txid = metaidOutpointBuf.slice(0, 32).reverse().toString("hex"); //reverse会改变原对象 let index = metaidOutpointBuf.readUIntLE(32, 4); let outpoint = { txid, index }; return outpoint; } exports.getMetaidOutpoint = getMetaidOutpoint; 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 outpoint = { txid, index }; return outpoint; } exports.getSensibleID = getSensibleID; function newDataPart({ metaidOutpoint, genesisFlag, nftAddress, totalSupply, tokenIndex, genesisHash, rabinPubKeyHashArrayHash, sensibleID, protoVersion, protoType, }) { let metaidOutpointBuf = Buffer.alloc(METAID_OUTPOINT_LEN, 0); if (metaidOutpoint && metaidOutpoint.txid) { const txidBuf = Buffer.from(metaidOutpoint.txid, "hex").reverse(); const indexBuf = Buffer.alloc(4, 0); indexBuf.writeUInt32LE(metaidOutpoint.index); metaidOutpointBuf = Buffer.concat([txidBuf, indexBuf]); } const genesisFlagBuf = Buffer.alloc(GENESIS_FLAG_LEN, 0); if (genesisFlag) { genesisFlagBuf.writeUInt8(genesisFlag); } const nftAddressBuf = Buffer.alloc(NFT_ADDRESS_LEN, 0); if (nftAddress) { nftAddressBuf.write(nftAddress, "hex"); } let totalSupplyBuf = Buffer.alloc(TOTAL_SUPPLY_LEN, 0); if (totalSupply) { totalSupplyBuf = totalSupply .toBuffer({ endian: "little", size: TOTAL_SUPPLY_LEN }) .slice(0, TOTAL_SUPPLY_LEN); } let tokenIndexBuf = Buffer.alloc(TOKEN_INDEX_LEN, 0); if (tokenIndex) { tokenIndexBuf = tokenIndex.toBuffer({ endian: "little", size: TOKEN_INDEX_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 protoVersionBuf = Buffer.alloc(proto.PROTO_VERSION_LEN); if (protoVersion) { protoVersionBuf.writeUInt32LE(protoVersion); } const protoTypeBuf = Buffer.alloc(proto.PROTO_TYPE_LEN, 0); if (protoType) { protoTypeBuf.writeUInt32LE(protoType); } return Buffer.concat([ metaidOutpointBuf, genesisFlagBuf, nftAddressBuf, totalSupplyBuf, tokenIndexBuf, genesisHashBuf, rabinPubKeyHashArrayHashBuf, sensibleIDBuf, protoVersionBuf, protoTypeBuf, proto.PROTO_FLAG, ]); } exports.newDataPart = newDataPart; function parseDataPart(scriptBuf) { let metaidOutpoint = getMetaidOutpoint(scriptBuf); let genesisFlag = getGenesisFlag(scriptBuf); let nftAddress = getNftAddress(scriptBuf); let totalSupply = getTotalSupply(scriptBuf); let tokenIndex = getTokenIndex(scriptBuf); let genesisHash = getGenesisHash(scriptBuf); let rabinPubKeyHashArrayHash = getRabinPubKeyHashArrayHash(scriptBuf); let sensibleID = getSensibleID(scriptBuf); let protoVersion = proto.getProtoVersioin(scriptBuf); let protoType = proto.getProtoType(scriptBuf); return { metaidOutpoint, genesisFlag, nftAddress, totalSupply, tokenIndex, genesisHash, rabinPubKeyHashArrayHash, sensibleID, protoVersion, protoType, }; } exports.parseDataPart = parseDataPart; function updateScript(scriptBuf, dataPartObj) { const firstBuf = scriptBuf.slice(0, scriptBuf.length - DATA_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)(bsv.crypto.Hash.sha256ripemd160(script.slice(script.length - GENESIS_HASH_OFFSET, script.length - proto.getHeaderLen()))); } 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;