meta-contract-debug
Version:
Meta Contract SDK
211 lines (210 loc) • 9.38 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseSensibleId = exports.getLatestGenesisInfo = exports.getNftInfo = exports.checkFeeRate = exports.unlockP2PKHInputs = exports.addChangeOutput = exports.addOpreturnOutput = exports.addContractOutput = exports.addContractInput = exports.addP2PKHInputs = exports.prepareUtxos = void 0;
const mvc_1 = require("../mvc");
const error_1 = require("../common/error");
const utils_1 = require("../common/utils");
const nftGenesis_1 = require("../mcp01/contract-factory/nftGenesis");
const tokenGenesis_1 = require("../mcp02/contract-factory/tokenGenesis");
const nftProto = require("../mcp01/contract-proto/nft.proto");
const ftProto = require("../mcp02/contract-proto/token.proto");
const mvc = require("../mvc");
function prepareUtxos(purse, api, network, utxosInput) {
return __awaiter(this, void 0, void 0, function* () {
let utxoPrivateKeys = [];
if (utxosInput) {
utxosInput.forEach((utxo) => {
if (utxo.wif) {
let privateKey = mvc.PrivateKey.fromWIF(utxo.wif);
utxoPrivateKeys.push(privateKey);
utxo.address = privateKey.toAddress(network); //Compatible with the old version, only wif is provided but no address is provided
}
});
return {
utxos: utxosInput,
utxoPrivateKeys,
};
}
const utxos = yield api.getUnspents(purse.address.toString());
utxos.forEach((utxo) => {
utxoPrivateKeys.push(purse.privateKey);
utxo.address = new mvc_1.Address(utxo.address, network);
});
if (utxos.length == 0)
throw new error_1.CodeError(error_1.ErrCode.EC_INSUFFICIENT_BSV, 'Insufficient balance.');
return { utxos, utxoPrivateKeys };
});
}
exports.prepareUtxos = prepareUtxos;
function addP2PKHInputs(txComposer, utxos) {
const p2pkhInputIndexes = utxos.map((utxo) => {
const inputIndex = txComposer.appendP2PKHInput(utxo);
txComposer.addSigHashInfo({
inputIndex,
address: utxo.address.toString(),
sighashType: utils_1.sighashType,
contractType: utils_1.CONTRACT_TYPE.P2PKH,
});
return inputIndex;
});
return p2pkhInputIndexes;
}
exports.addP2PKHInputs = addP2PKHInputs;
function addContractInput(txComposer, contractUTxo, address, contractType) {
const contractInputIndex = txComposer.appendInput(contractUTxo);
txComposer.addSigHashInfo({
inputIndex: contractInputIndex,
address,
sighashType: utils_1.sighashType,
contractType,
});
return contractInputIndex;
}
exports.addContractInput = addContractInput;
function addContractOutput({ txComposer, contract, lockingScript, dustCalculator, }) {
if (!lockingScript) {
lockingScript = contract.lockingScript;
}
const contractSize = lockingScript.toBuffer().length;
const satoshis = dustCalculator.getDustThreshold(contractSize);
return txComposer.appendOutput({
lockingScript,
satoshis,
});
}
exports.addContractOutput = addContractOutput;
function addOpreturnOutput(txComposer, opreturnData) {
return txComposer.appendOpReturnOutput(opreturnData);
}
exports.addOpreturnOutput = addOpreturnOutput;
function addChangeOutput(txComposer, changeAddress, feeb) {
return txComposer.appendChangeOutput(changeAddress, feeb);
}
exports.addChangeOutput = addChangeOutput;
function unlockP2PKHInputs(txComposer, inputIndexes, utxoPrivateKeys) {
inputIndexes.forEach((inputIndex) => {
let privateKey = utxoPrivateKeys.splice(0, 1)[0];
txComposer.unlockP2PKHInput(privateKey, inputIndex);
});
}
exports.unlockP2PKHInputs = unlockP2PKHInputs;
function checkFeeRate(txComposer, feeb) {
let feeRate = txComposer.getFeeRate();
if (feeRate < feeb) {
throw new error_1.CodeError(error_1.ErrCode.EC_INSUFFICIENT_BSV, `Insufficient balance.The fee rate should not be less than ${feeb}, but in the end it is ${feeRate}.`);
}
}
exports.checkFeeRate = checkFeeRate;
function getNftInfo({ tokenIndex, codehash, genesis, api, network, }) {
return __awaiter(this, void 0, void 0, function* () {
let _res = yield api.getNonFungibleTokenUnspentDetail(codehash, genesis, tokenIndex);
let nftUtxo = {
txId: _res.txId,
outputIndex: _res.outputIndex,
nftAddress: new mvc_1.Address(_res.tokenAddress, network),
};
return { nftUtxo };
});
}
exports.getNftInfo = getNftInfo;
// 获取最新的创世合约及tx信息
function getLatestGenesisInfo({ sensibleId, api, address, type, }) {
return __awaiter(this, void 0, void 0, function* () {
const factory = type === 'nft' ? nftGenesis_1.NftGenesisFactory : tokenGenesis_1.TokenGenesisFactory;
const proto = type === 'nft' ? nftProto : ftProto;
let genesisContract = factory.createContract();
let { genesisTxId, genesisOutputIndex } = parseSensibleId(sensibleId);
let genesisUtxo = yield getLatestGenesisUtxo(proto, genesisContract.getCodeHash(), genesisTxId, genesisOutputIndex, api, address, type);
if (!genesisUtxo) {
throw new error_1.CodeError(error_1.ErrCode.EC_FIXED_TOKEN_SUPPLY, 'token supply is fixed');
}
let txHex = yield api.getRawTxData(genesisUtxo.txId);
const tx = new mvc_1.Transaction(txHex);
let preTxId = tx.inputs[0].prevTxId.toString('hex');
let preOutputIndex = tx.inputs[0].outputIndex;
let preTxHex = yield api.getRawTxData(preTxId);
genesisUtxo.satotxInfo = {
txId: genesisUtxo.txId,
outputIndex: genesisUtxo.outputIndex,
txHex,
preTxId,
preOutputIndex,
preTxHex,
};
let output = tx.outputs[genesisUtxo.outputIndex];
genesisUtxo.satoshis = output.satoshis;
genesisUtxo.lockingScript = output.script;
genesisContract.setFormatedDataPartFromLockingScript(genesisUtxo.lockingScript);
return {
genesisContract,
genesisTxId,
genesisOutputIndex,
genesisUtxo,
};
});
}
exports.getLatestGenesisInfo = getLatestGenesisInfo;
function getLatestGenesisUtxo(proto, codehash, genesisTxId, genesisOutputIndex, api, address, type) {
return __awaiter(this, void 0, void 0, function* () {
// 使用创世txid从接口获取该创世tx内容
let unspent;
let latestGenesisTxHex = yield api.getRawTxData(genesisTxId);
let latestGenesisTx = new mvc_1.Transaction(latestGenesisTxHex);
// 重新构建该创世脚本
let scriptBuffer = latestGenesisTx.outputs[genesisOutputIndex].script.toBuffer();
let originGenesis = proto.getQueryGenesis(scriptBuffer);
// 找回utxo
let genesisUtxos;
if (type === 'nft') {
genesisUtxos = yield api.getNonFungibleTokenUnspents(codehash, originGenesis, address.toString());
}
else {
genesisUtxos = yield api.getFungibleTokenUnspents(codehash, originGenesis, address.toString());
}
unspent = genesisUtxos.find((v) => v.txId == genesisTxId && v.outputIndex == genesisOutputIndex);
if (!unspent) {
let _dataPartObj = proto.parseDataPart(scriptBuffer);
_dataPartObj.sensibleID = {
txid: genesisTxId,
index: genesisOutputIndex,
};
let newScriptBuf = proto.updateScript(scriptBuffer, _dataPartObj);
let issueGenesis = proto.getQueryGenesis(newScriptBuf);
let issueUtxos;
if (type === 'nft') {
issueUtxos = yield api.getNonFungibleTokenUnspents(codehash, issueGenesis, address.toString());
}
else {
issueUtxos = yield api.getFungibleTokenUnspents(codehash, issueGenesis, address.toString());
}
if (issueUtxos.length > 0) {
unspent = issueUtxos[0];
}
}
if (unspent) {
return {
txId: unspent.txId,
outputIndex: unspent.outputIndex,
};
}
});
}
function parseSensibleId(sensibleId) {
let sensibleIDBuf = Buffer.from(sensibleId, 'hex');
let genesisTxId = sensibleIDBuf.slice(0, 32).reverse().toString('hex');
let genesisOutputIndex = sensibleIDBuf.readUIntLE(32, 4);
return {
genesisTxId,
genesisOutputIndex,
};
}
exports.parseSensibleId = parseSensibleId;