UNPKG

meta-contract

Version:

Meta Contract SDK

218 lines (217 loc) 9.54 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.getNftAddress = exports.getTotalSupply = exports.getNftID = exports.getTokenIndex = exports.getGenesisHash = exports.EMPTY_ADDRESS = exports.GENESIS_TOKEN_ID = exports.PROTO_VERSION = exports.NFT_OP_TYPE = void 0; const mvc = require("../../mvc"); const proto = require("../../common/protoheader"); const Utils = require("../../common/utils"); const scryptlib_1 = require("../../scryptlib"); const BN = require("../../bn.js"); const tokenUtil_1 = require("../../common/tokenUtil"); 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; // <type specific data> + <proto header> // <proto header> = <type(4 bytes)> + <'sensible'(8 bytes)> //<nft type specific data> = <metaid_outpoint(36 bytes)> + <address(20 bytes)> + <totalSupply(8 bytes) + <tokenIndex(8 bytes)> + <genesisHash<20 bytes>) + + <sensibleID(36 bytes)> const SENSIBLE_ID_LEN = 36; 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 METAID_OUTPOINT_LEN = 36; const SENSIBLE_ID_OFFSET = SENSIBLE_ID_LEN + proto.getHeaderLen(); const GENESIS_HASH_OFFSET = SENSIBLE_ID_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 METAID_OUTPOINT_OFFSET = NFT_ADDRESS_OFFSET + METAID_OUTPOINT_LEN; const DATA_LEN = METAID_OUTPOINT_OFFSET; // const OP_PUSH_LEN = 2 // const DATA_LEN = METAID_OUTPOINT_OFFSET + OP_PUSH_LEN exports.GENESIS_TOKEN_ID = Buffer.alloc(NFT_ID_LEN, 0); exports.EMPTY_ADDRESS = Buffer.alloc(NFT_ADDRESS_LEN, 0); 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; // sensibleID function getNftID(script) { return mvc.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 getContractCode(script) { return script.slice(0, script.length - DATA_LEN - Utils.getVarPushdataHeader(DATA_LEN).length); } exports.getContractCode = getContractCode; function getContractCodeHash(script) { return mvc.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, nftAddress, totalSupply, tokenIndex, genesisHash, 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]); } let nftAddressBuf = Buffer.alloc(NFT_ADDRESS_LEN, 0); if (nftAddress) { // nftAddressBuf.write(nftAddress, 'hex') nftAddressBuf = Buffer.from(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'); } 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); } const buf = Buffer.concat([ metaidOutpointBuf, nftAddressBuf, totalSupplyBuf, tokenIndexBuf, genesisHashBuf, sensibleIDBuf, protoVersionBuf, protoTypeBuf, proto.PROTO_FLAG, ]); return (0, tokenUtil_1.buildScriptData)(buf); } exports.newDataPart = newDataPart; function parseDataPart(scriptBuf) { let metaidOutpoint = getMetaidOutpoint(scriptBuf); let nftAddress = getNftAddress(scriptBuf); let totalSupply = getTotalSupply(scriptBuf); let tokenIndex = getTokenIndex(scriptBuf); let genesisHash = getGenesisHash(scriptBuf); let sensibleID = getSensibleID(scriptBuf); let protoVersion = proto.getProtoVersion(scriptBuf); let protoType = proto.getProtoType(scriptBuf); // const scriptHexLen = scriptBuf.toString('hex').length // const scriptLen = scriptBuf.length // const protoVersion1 = proto.getProtoVersion(scriptBuf) // const protoVersion2 = scriptBuf.toString('hex').slice(scriptHexLen - 40, scriptHexLen - 32) // const metacontract = Buffer.from('metacontract') // const metacontract2 = proto.getFlag(scriptBuf) // console.log( // 'parsing', // scriptBuf.toString('hex'), // scriptHexLen, // scriptLen, // protoVersion1, // protoVersion2, // metacontract.toString('hex'), // metacontract2.toString('hex'), // proto.PROTO_FLAG_LEN, // proto.PROTO_FLAG.toString('hex') // ) return { metaidOutpoint, nftAddress, totalSupply, tokenIndex, genesisHash, 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)(mvc.crypto.Hash.sha256ripemd160(script.slice(script.length - GENESIS_HASH_OFFSET, script.length - proto.getHeaderLen()) // [len - (20+36+25), len - 25] )); } 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;