858 lines
41 KiB
JavaScript
858 lines
41 KiB
JavaScript
"use strict";
|
|
var __assign = (this && this.__assign) || function () {
|
|
__assign = Object.assign || function(t) {
|
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
s = arguments[i];
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
t[p] = s[p];
|
|
}
|
|
return t;
|
|
};
|
|
return __assign.apply(this, arguments);
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.CARDANO_CHIMERIC = exports.CARDANO_CHANGE = exports.CARDANO_EXTERNAL = exports.CARDANO_COIN_TYPE = exports.CARDANO_PUROPOSE = exports.MetadateTypesEnum = exports.Bip32KeyPair = exports.Seed = void 0;
|
|
var bip39_1 = require("bip39");
|
|
var cardano_serialization_lib_nodejs_1 = require("@emurgo/cardano-serialization-lib-nodejs");
|
|
var network_config_1 = require("./config/network.config");
|
|
var json_script_model_1 = require("./models/json-script.model");
|
|
var payment_extended_signing_key_1 = require("./models/payment-extended-signing-key");
|
|
var multisig_transaction_1 = require("./models/multisig-transaction");
|
|
var phrasesLengthMap = {
|
|
12: 128,
|
|
15: 160,
|
|
18: 192,
|
|
21: 224,
|
|
24: 256
|
|
};
|
|
var Seed = /** @class */ (function () {
|
|
function Seed() {
|
|
}
|
|
Seed.generateRecoveryPhrase = function (size) {
|
|
if (size === void 0) { size = 15; }
|
|
var strength = phrasesLengthMap[size] || phrasesLengthMap[15];
|
|
return bip39_1.generateMnemonic(strength).trim();
|
|
};
|
|
Seed.toMnemonicList = function (phrase) {
|
|
return phrase.trim().split(/\s+/g);
|
|
};
|
|
Seed.deriveRootKey = function (phrase) {
|
|
var mnemonic = Array.isArray(phrase) ? phrase.join(' ') : phrase;
|
|
var entropy = bip39_1.mnemonicToEntropy(mnemonic);
|
|
var rootKey = cardano_serialization_lib_nodejs_1.Bip32PrivateKey.from_bip39_entropy(Buffer.from(entropy, 'hex'), Buffer.from(''));
|
|
return rootKey;
|
|
};
|
|
Seed.deriveAccountKey = function (key, index) {
|
|
if (index === void 0) { index = 0; }
|
|
return key
|
|
.derive(Seed.harden(exports.CARDANO_PUROPOSE)) // purpose
|
|
.derive(Seed.harden(exports.CARDANO_COIN_TYPE)) // coin type
|
|
.derive(Seed.harden(index)); // account #0
|
|
};
|
|
Seed.deriveKey = function (key, path) {
|
|
var result = key;
|
|
path.forEach(function (p) {
|
|
result = result.derive(p.endsWith('H') || p.endsWith("'")
|
|
? Seed.harden(Number.parseInt(p.substr(0, p.length - 1)))
|
|
: Number.parseInt(p));
|
|
});
|
|
return result;
|
|
};
|
|
Seed.buildTransaction = function (coinSelection, ttl, opts) {
|
|
var _a, _b;
|
|
if (opts === void 0) { opts = {
|
|
changeAddress: '',
|
|
metadata: null,
|
|
startSlot: 0,
|
|
config: network_config_1.Mainnet
|
|
}; }
|
|
var config = opts.config || network_config_1.Mainnet;
|
|
var metadata = opts.metadata;
|
|
var startSlot = opts.startSlot || 0;
|
|
var tbConfig = cardano_serialization_lib_nodejs_1.TransactionBuilderConfigBuilder.new()
|
|
// all of these are taken from the mainnet genesis settings
|
|
// linear fee parameters (a*size + b)
|
|
.fee_algo(cardano_serialization_lib_nodejs_1.LinearFee.new(toBigNum(config.protocolParams.txFeePerByte), toBigNum(config.protocolParams.txFeeFixed)))
|
|
//min-ada-value
|
|
.coins_per_utxo_word(toBigNum(config.protocolParams.utxoCostPerWord))
|
|
// pool deposit
|
|
.pool_deposit(toBigNum(config.protocolParams.stakePoolDeposit))
|
|
// key deposit
|
|
.key_deposit(toBigNum(config.protocolParams.stakeAddressDeposit))
|
|
// max output value size
|
|
.max_value_size(config.protocolParams.maxValueSize)
|
|
// max tx size
|
|
.max_tx_size(config.protocolParams.maxTxSize)
|
|
.build();
|
|
var txBuilder = cardano_serialization_lib_nodejs_1.TransactionBuilder.new(tbConfig);
|
|
// add tx inputs
|
|
coinSelection.inputs.forEach(function (input, i) {
|
|
var address = cardano_serialization_lib_nodejs_1.Address.from_bech32(input.address);
|
|
var txInput = cardano_serialization_lib_nodejs_1.TransactionInput.new(cardano_serialization_lib_nodejs_1.TransactionHash.from_bytes(Buffer.from(input.id, 'hex')), input.index);
|
|
var amount = cardano_serialization_lib_nodejs_1.Value.new(toBigNum(input.amount.quantity));
|
|
txBuilder.add_input(address, txInput, amount);
|
|
});
|
|
// add tx outputs
|
|
coinSelection.outputs.forEach(function (output) {
|
|
var address = cardano_serialization_lib_nodejs_1.Address.from_bech32(output.address);
|
|
var amount = cardano_serialization_lib_nodejs_1.Value.new(toBigNum(output.amount.quantity));
|
|
// add tx assets
|
|
if (output.assets && output.assets.length > 0) {
|
|
var multiAsset = Seed.buildMultiAssets(output.assets);
|
|
amount.set_multiasset(multiAsset);
|
|
}
|
|
var txOutput = cardano_serialization_lib_nodejs_1.TransactionOutput.new(address, amount);
|
|
txBuilder.add_output(txOutput);
|
|
});
|
|
// add tx change
|
|
coinSelection.change.forEach(function (change) {
|
|
var address = cardano_serialization_lib_nodejs_1.Address.from_bech32(change.address);
|
|
var amount = cardano_serialization_lib_nodejs_1.Value.new(toBigNum(change.amount.quantity));
|
|
// add tx assets
|
|
if (change.assets && change.assets.length > 0) {
|
|
var multiAsset = Seed.buildMultiAssets(change.assets);
|
|
amount.set_multiasset(multiAsset);
|
|
}
|
|
var txOutput = cardano_serialization_lib_nodejs_1.TransactionOutput.new(address, amount);
|
|
txBuilder.add_output(txOutput);
|
|
});
|
|
// add tx metadata
|
|
if (metadata) {
|
|
txBuilder.set_auxiliary_data(metadata);
|
|
}
|
|
// set tx validity start interval
|
|
txBuilder.set_validity_start_interval(startSlot);
|
|
// set tx ttl
|
|
txBuilder.set_ttl(ttl);
|
|
// calculate fee
|
|
if (opts.changeAddress) {
|
|
// don't take the implicit fee
|
|
var address = cardano_serialization_lib_nodejs_1.Address.from_bech32(opts.changeAddress);
|
|
txBuilder.add_change_if_needed(address);
|
|
}
|
|
else {
|
|
var fee = opts.fee ||
|
|
coinSelection.inputs.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) +
|
|
(((_a = coinSelection.withdrawals) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0)) || 0) -
|
|
coinSelection.outputs.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) -
|
|
coinSelection.change.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) -
|
|
(((_b = coinSelection.deposits) === null || _b === void 0 ? void 0 : _b.reduce(function (acc, c) { return c.quantity + acc; }, 0)) || 0);
|
|
txBuilder.set_fee(toBigNum(fee));
|
|
}
|
|
var txBody = txBuilder.build();
|
|
return txBody;
|
|
};
|
|
Seed.buildTransactionWithToken = function (coinSelection, ttl, tokens, signingKeys, opts, encoding) {
|
|
var _a, _b;
|
|
if (opts === void 0) { opts = {
|
|
changeAddress: '',
|
|
data: null,
|
|
startSlot: 0,
|
|
config: network_config_1.Mainnet
|
|
}; }
|
|
if (encoding === void 0) { encoding = 'hex'; }
|
|
var metadata = opts.data ? Seed.buildTransactionMetadata(opts.data) : null;
|
|
opts.config = opts.config || network_config_1.Mainnet;
|
|
// set maximun fee first
|
|
var fee = parseInt(opts.config.protocolParams.maxTxSize *
|
|
opts.config.protocolParams.txFeePerByte +
|
|
opts.config.protocolParams.txFeeFixed); // 16384 * 44 + 155381 = 876277
|
|
if (!opts.fee) {
|
|
opts.fee = fee;
|
|
// adjust change if there is any
|
|
if (coinSelection.change && coinSelection.change.length > 0) {
|
|
var selectionfee = coinSelection.inputs.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) +
|
|
(((_a = coinSelection.withdrawals) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0)) || 0) -
|
|
coinSelection.outputs.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) -
|
|
coinSelection.change.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) -
|
|
(((_b = coinSelection.deposits) === null || _b === void 0 ? void 0 : _b.reduce(function (acc, c) { return c.quantity + acc; }, 0)) || 0);
|
|
var feePerChange_1 = Math.ceil((opts.fee - selectionfee) / coinSelection.change.length);
|
|
coinSelection.change = coinSelection.change.map(function (change) {
|
|
change.amount.quantity -= feePerChange_1;
|
|
return change;
|
|
});
|
|
}
|
|
}
|
|
var buildOpts = Object.assign({}, __assign({ metadata: metadata }, opts));
|
|
// create mint token data
|
|
var mint = Seed.buildTransactionMint(tokens, encoding);
|
|
// get token's scripts
|
|
var scripts = tokens.map(function (t) { return t.script; });
|
|
// set mint into tx
|
|
var txBody = Seed.buildTransaction(coinSelection, ttl, buildOpts);
|
|
txBody.set_mint(mint);
|
|
// sign to calculate the real tx fee;
|
|
var tx = Seed.sign(txBody, signingKeys, metadata, scripts);
|
|
// NOTE: txFee should be <= original fee = maxTxSize * txFeePerByte + txFeeFixed
|
|
// Also after rearrange the outputs will decrease along with fee field, so new tx fee won't increase because tx's size (bytes) will be smaller;
|
|
var txFee = parseInt(Seed.getTransactionFee(tx, opts.config).to_str());
|
|
// if (txFee > fee) throw new Error(`expected tx size less than ${opts.config.protocolParams.maxTxSize} but got: ${(txFee - opts.config.protocolParams.txFeeFixed)/opts.config.protocolParams.txFeePerByte}`)
|
|
var finalFee = txFee;
|
|
// const finalFee = Math.min(txFee, (fee || Number.MAX_SAFE_INTEGER)); // we'll use the min fee on final tx
|
|
opts.fee = finalFee;
|
|
// adjust change UTXO
|
|
var feeDiff = fee - finalFee;
|
|
if (coinSelection.change && coinSelection.change.length > 0) {
|
|
var feeDiffPerChange_1 = Math.ceil(feeDiff / coinSelection.change.length);
|
|
coinSelection.change = coinSelection.change.map(function (c) {
|
|
c.amount.quantity += feeDiffPerChange_1;
|
|
return c;
|
|
});
|
|
}
|
|
// after signing the metadata is cleaned so we need to create it again
|
|
metadata = opts.data ? Seed.buildTransactionMetadata(opts.data) : null;
|
|
buildOpts = Object.assign({}, __assign({ metadata: metadata }, opts));
|
|
txBody = Seed.buildTransaction(coinSelection, ttl, buildOpts);
|
|
txBody.set_mint(mint);
|
|
return txBody;
|
|
};
|
|
Seed.buildTransactionMultisig = function (coinSelection, ttl, scripts, tokens, signingKeys, opts, encoding) {
|
|
var _a, _b;
|
|
if (tokens === void 0) { tokens = null; }
|
|
if (signingKeys === void 0) { signingKeys = null; }
|
|
if (opts === void 0) { opts = {
|
|
changeAddress: '',
|
|
data: null,
|
|
startSlot: 0,
|
|
config: network_config_1.Mainnet
|
|
}; }
|
|
if (encoding === void 0) { encoding = 'hex'; }
|
|
var config = opts.config || network_config_1.Mainnet;
|
|
var metadata = opts.data ? Seed.buildTransactionMetadata(opts.data) : null;
|
|
var startSlot = opts.startSlot || 0;
|
|
var selectionfee = parseInt(config.protocolParams.maxTxSize * config.protocolParams.txFeePerByte +
|
|
config.protocolParams.txFeeFixed); // 16384 * 44 + 155381 = 876277
|
|
var currentfee = coinSelection.inputs.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) +
|
|
(((_a = coinSelection.withdrawals) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0)) || 0) -
|
|
coinSelection.outputs.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) -
|
|
coinSelection.change.reduce(function (acc, c) { return c.amount.quantity + acc; }, 0) -
|
|
(((_b = coinSelection.deposits) === null || _b === void 0 ? void 0 : _b.reduce(function (acc, c) { return c.quantity + acc; }, 0)) || 0);
|
|
// add witnesses Ed25519KeyHash from input addresses
|
|
var vkeys = {};
|
|
// add tx inputs
|
|
var inputs = coinSelection.inputs.map(function (input, i) {
|
|
// check if input is vkeywitness
|
|
var addr = cardano_serialization_lib_nodejs_1.Address.from_bech32(input.address);
|
|
var baseAddr = cardano_serialization_lib_nodejs_1.BaseAddress.from_address(addr);
|
|
var inputHash = baseAddr.payment_cred().to_keyhash();
|
|
if (inputHash) {
|
|
vkeys[inputHash.to_bech32('vkey_')] =
|
|
(vkeys[inputHash.to_bech32('vkey_')] || 0) + 1;
|
|
}
|
|
return cardano_serialization_lib_nodejs_1.TransactionInput.new(cardano_serialization_lib_nodejs_1.TransactionHash.from_bytes(Buffer.from(input.id, 'hex')), input.index);
|
|
});
|
|
// add tx outputs
|
|
var outputs = coinSelection.outputs.map(function (output) {
|
|
var address = cardano_serialization_lib_nodejs_1.Address.from_bech32(output.address);
|
|
var amount = cardano_serialization_lib_nodejs_1.Value.new(toBigNum(output.amount.quantity));
|
|
// add tx assets
|
|
if (output.assets && output.assets.length > 0) {
|
|
var multiAsset = Seed.buildMultiAssets(output.assets, encoding);
|
|
amount.set_multiasset(multiAsset);
|
|
}
|
|
return cardano_serialization_lib_nodejs_1.TransactionOutput.new(address, amount);
|
|
});
|
|
// adjust changes to match maximum fee
|
|
if (coinSelection.change && coinSelection.change.length > 0) {
|
|
var feeDiff = selectionfee - currentfee;
|
|
var feeDiffPerChange = Math.abs(Math.ceil(feeDiff / coinSelection.change.length));
|
|
for (var i = 0; i < coinSelection.change.length; i++) {
|
|
var change = coinSelection.change[i];
|
|
change.amount.quantity =
|
|
feeDiff > 0
|
|
? change.amount.quantity - feeDiffPerChange
|
|
: change.amount.quantity + feeDiffPerChange;
|
|
var address = cardano_serialization_lib_nodejs_1.Address.from_bech32(change.address);
|
|
var amount = cardano_serialization_lib_nodejs_1.Value.new(toBigNum(change.amount.quantity));
|
|
// add tx assets
|
|
if (change.assets && change.assets.length > 0) {
|
|
var multiAsset = Seed.buildMultiAssets(change.assets, encoding);
|
|
amount.set_multiasset(multiAsset);
|
|
}
|
|
var out = cardano_serialization_lib_nodejs_1.TransactionOutput.new(address, amount);
|
|
outputs.push(out);
|
|
}
|
|
}
|
|
var txInputs = cardano_serialization_lib_nodejs_1.TransactionInputs.new();
|
|
inputs.forEach(function (txin) { return txInputs.add(txin); });
|
|
var txOutputs = cardano_serialization_lib_nodejs_1.TransactionOutputs.new();
|
|
outputs.forEach(function (txout) { return txOutputs.add(txout); });
|
|
var txBody = cardano_serialization_lib_nodejs_1.TransactionBody.new(txInputs, txOutputs, toBigNum(selectionfee), ttl);
|
|
// add tx metadata
|
|
if (metadata) {
|
|
var dataHash = cardano_serialization_lib_nodejs_1.hash_auxiliary_data(metadata);
|
|
txBody.set_auxiliary_data_hash(dataHash);
|
|
}
|
|
if (tokens) {
|
|
// create mint token data
|
|
var mint = Seed.buildTransactionMint(tokens, encoding);
|
|
txBody.set_mint(mint);
|
|
}
|
|
// set tx validity start interval
|
|
txBody.set_validity_start_interval(startSlot);
|
|
var numOfWitnesses = Object.values(vkeys).reduce(function (total, cur) { return total + cur; }, 0) +
|
|
scripts.reduce(function (t, c) { return t + c.get_required_signers().len(); }, 0);
|
|
return multisig_transaction_1.MultisigTransaction.new(coinSelection, txBody, scripts, signingKeys, numOfWitnesses, config, encoding, metadata, tokens);
|
|
};
|
|
Seed.buildMultiAssets = function (assets, encoding) {
|
|
if (encoding === void 0) { encoding = 'hex'; }
|
|
var multiAsset = cardano_serialization_lib_nodejs_1.MultiAsset.new();
|
|
var groups = assets.reduce(function (dict, asset) {
|
|
;
|
|
(dict[asset.policy_id] = dict[asset.policy_id] || []).push(asset);
|
|
return dict;
|
|
}, {});
|
|
for (var policy_id in groups) {
|
|
var scriptHash = Seed.getScriptHashFromPolicy(policy_id);
|
|
var asset = cardano_serialization_lib_nodejs_1.Assets.new();
|
|
var assetGroups = groups[policy_id].reduce(function (dict, asset) {
|
|
dict[asset.asset_name] =
|
|
(dict[asset.asset_name] || 0) + +asset.quantity;
|
|
return dict;
|
|
}, {});
|
|
for (var asset_name in assetGroups) {
|
|
var quantity = assetGroups[asset_name];
|
|
var assetName = cardano_serialization_lib_nodejs_1.AssetName.new(Buffer.from(asset_name, encoding));
|
|
asset.insert(assetName, toBigNum(quantity));
|
|
}
|
|
multiAsset.insert(scriptHash, asset);
|
|
}
|
|
return multiAsset;
|
|
};
|
|
Seed.buildTransactionMint = function (tokens, encoding) {
|
|
if (encoding === void 0) { encoding = 'utf8'; }
|
|
var mint = cardano_serialization_lib_nodejs_1.Mint.new();
|
|
var groups = tokens.reduce(function (dict, asset) {
|
|
;
|
|
(dict[asset.asset.policy_id] = dict[asset.asset.policy_id] || []).push(asset);
|
|
return dict;
|
|
}, {});
|
|
for (var policy_id in groups) {
|
|
var scriptHash = Seed.getScriptHashFromPolicy(policy_id);
|
|
var mintAssets = cardano_serialization_lib_nodejs_1.MintAssets.new();
|
|
var assetGroups = groups[policy_id].reduce(function (dict, asset) {
|
|
dict[asset.asset.asset_name] =
|
|
(dict[asset.asset.asset_name] || 0) + +asset.asset.quantity;
|
|
return dict;
|
|
}, {});
|
|
for (var asset_name in assetGroups) {
|
|
var quantity = assetGroups[asset_name];
|
|
var assetName = cardano_serialization_lib_nodejs_1.AssetName.new(Buffer.from(asset_name, encoding));
|
|
mintAssets.insert(assetName, cardano_serialization_lib_nodejs_1.Int.new(toBigNum(quantity)));
|
|
}
|
|
mint.insert(scriptHash, mintAssets);
|
|
}
|
|
return mint;
|
|
};
|
|
Seed.getTransactionFee = function (tx, config) {
|
|
if (config === void 0) { config = network_config_1.Mainnet; }
|
|
return cardano_serialization_lib_nodejs_1.min_fee(tx, cardano_serialization_lib_nodejs_1.LinearFee.new(toBigNum(config.protocolParams.txFeePerByte), toBigNum(config.protocolParams.txFeeFixed)));
|
|
};
|
|
Seed.addKeyWitness = function (transaction, prvKey) {
|
|
var vkeyWitnesses = cardano_serialization_lib_nodejs_1.Vkeywitnesses.new();
|
|
var txBody = transaction.body();
|
|
var txHash = cardano_serialization_lib_nodejs_1.hash_transaction(txBody);
|
|
var vkeyWitness = cardano_serialization_lib_nodejs_1.make_vkey_witness(txHash, prvKey);
|
|
vkeyWitnesses.add(vkeyWitness);
|
|
var witnesses = transaction.witness_set();
|
|
witnesses.set_vkeys(vkeyWitnesses);
|
|
return cardano_serialization_lib_nodejs_1.Transaction.new(txBody, witnesses, transaction.auxiliary_data());
|
|
};
|
|
Seed.addScriptWitness = function (transaction, script) {
|
|
var txBody = transaction.body();
|
|
var nativeScripts = cardano_serialization_lib_nodejs_1.NativeScripts.new();
|
|
nativeScripts.add(script);
|
|
var witnesses = transaction.witness_set();
|
|
witnesses.set_native_scripts(nativeScripts);
|
|
return cardano_serialization_lib_nodejs_1.Transaction.new(txBody, witnesses, transaction.auxiliary_data());
|
|
};
|
|
Seed.sign = function (txBody, privateKeys, transactionMetadata, scripts) {
|
|
var txHash = cardano_serialization_lib_nodejs_1.hash_transaction(txBody);
|
|
var witnesses = cardano_serialization_lib_nodejs_1.TransactionWitnessSet.new();
|
|
var vkeyWitnesses = cardano_serialization_lib_nodejs_1.Vkeywitnesses.new();
|
|
if (privateKeys) {
|
|
privateKeys.forEach(function (prvKey) {
|
|
// add keyhash witnesses
|
|
var vkeyWitness = cardano_serialization_lib_nodejs_1.make_vkey_witness(txHash, prvKey);
|
|
vkeyWitnesses.add(vkeyWitness);
|
|
});
|
|
}
|
|
witnesses.set_vkeys(vkeyWitnesses);
|
|
if (scripts) {
|
|
var nativeScripts_1 = cardano_serialization_lib_nodejs_1.NativeScripts.new();
|
|
scripts.forEach(function (s) {
|
|
nativeScripts_1.add(s);
|
|
});
|
|
witnesses.set_native_scripts(nativeScripts_1);
|
|
}
|
|
var transaction = cardano_serialization_lib_nodejs_1.Transaction.new(txBody, witnesses, transactionMetadata);
|
|
return transaction;
|
|
};
|
|
Seed.signMessage = function (key, message) {
|
|
return key.sign(Buffer.from(message)).to_hex();
|
|
};
|
|
Seed.verifyMessage = function (key, message, signed) {
|
|
return key.verify(Buffer.from(message), cardano_serialization_lib_nodejs_1.Ed25519Signature.from_hex(signed));
|
|
};
|
|
Seed.getTxId = function (transaction) {
|
|
var txBody = transaction.body();
|
|
var txHash = cardano_serialization_lib_nodejs_1.hash_transaction(txBody);
|
|
var txId = Buffer.from(txHash.to_bytes()).toString('hex');
|
|
return txId;
|
|
};
|
|
Seed.convertPrivateKeyToSignKey = function (prkKey) {
|
|
// const k = Bip32PrivateKey.from_bech32(scriptKeys[1]);
|
|
console.log(prkKey.to_bech32());
|
|
// const hex = Buffer.from(prkKey.to_raw_key().as_bytes()).toString('hex');
|
|
var cborHex = '5880' + Buffer.from(prkKey.to_128_xprv()).toString('hex');
|
|
return new payment_extended_signing_key_1.ExtendedSigningKey(cborHex);
|
|
// console.log(hex);
|
|
};
|
|
Seed.harden = function (num) {
|
|
return 0x80000000 + num;
|
|
};
|
|
Seed.constructMetadata = function (data) {
|
|
var metadata = {};
|
|
if (Array.isArray(data)) {
|
|
for (var i = 0; i < data.length; i++) {
|
|
var value = data[i];
|
|
metadata[i] = Seed.getMetadataObject(value);
|
|
}
|
|
}
|
|
else {
|
|
var keys = Object.keys(data);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
if (this.isInteger(key)) {
|
|
var index = parseInt(key);
|
|
metadata[index] = Seed.getMetadataObject(data[key]);
|
|
}
|
|
}
|
|
}
|
|
return metadata;
|
|
};
|
|
Seed.getMetadataObject = function (data) {
|
|
var _this = this;
|
|
var result = {};
|
|
var type = typeof data;
|
|
if (type == 'number') {
|
|
result[MetadateTypesEnum.Number] = data;
|
|
}
|
|
else if (type == 'string' && Buffer.byteLength(data, 'utf-8') <= 64) {
|
|
result[MetadateTypesEnum.String] = data;
|
|
}
|
|
else if (Buffer.isBuffer(data) && Buffer.byteLength(data, 'hex') <= 64) {
|
|
result[MetadateTypesEnum.Bytes] = data.toString('hex');
|
|
}
|
|
else if (type == 'boolean') {
|
|
result[MetadateTypesEnum.String] = data.toString();
|
|
}
|
|
else if (type == 'undefined') {
|
|
result[MetadateTypesEnum.String] = 'undefined';
|
|
}
|
|
else if (Array.isArray(data)) {
|
|
result[MetadateTypesEnum.List] = data.map(function (a) {
|
|
return _this.getMetadataObject(a);
|
|
});
|
|
}
|
|
else if (type == 'object') {
|
|
if (data) {
|
|
result[MetadateTypesEnum.Map] = Object.keys(data).map(function (k) {
|
|
return {
|
|
k: _this.getMetadataObject(k),
|
|
v: _this.getMetadataObject(data[k])
|
|
};
|
|
});
|
|
}
|
|
else {
|
|
result[MetadateTypesEnum.String] = 'null';
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
Seed.reverseMetadata = function (data, type) {
|
|
if (type === void 0) { type = 'object'; }
|
|
if (!data) {
|
|
return null;
|
|
}
|
|
var metadata = type == 'object' ? {} : [];
|
|
var keys = Object.keys(data);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
var index = parseInt(key);
|
|
metadata[index] = Seed.reverseMetadataObject(data[key]);
|
|
}
|
|
return metadata;
|
|
};
|
|
Seed.reverseMetadataObject = function (data) {
|
|
var result = [];
|
|
var keys = Object.keys(data);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
var value = data[key];
|
|
if (key == 'string') {
|
|
result.push(value);
|
|
}
|
|
else if (key == 'int') {
|
|
result.push(new Number(value));
|
|
}
|
|
else if (key == 'bytes') {
|
|
result.push(Buffer.from(value, 'hex'));
|
|
}
|
|
else if (key == 'list') {
|
|
result.push(value.map(function (d) { return Seed.reverseMetadataObject(d); }));
|
|
}
|
|
else if (key == 'map') {
|
|
var map = value.reduce(function (acc, obj) {
|
|
var k = Seed.reverseMetadataObject(obj['k']);
|
|
var v = Seed.reverseMetadataObject(obj['v']);
|
|
acc[k] = v;
|
|
return acc;
|
|
}, {});
|
|
result.push(map);
|
|
}
|
|
else {
|
|
result.push(null);
|
|
}
|
|
}
|
|
return result.length == 1 ? result[0] : result;
|
|
};
|
|
Seed.buildTransactionMetadata = function (data) {
|
|
var metadata = Seed.constructMetadata(data);
|
|
var generalMetatada = cardano_serialization_lib_nodejs_1.GeneralTransactionMetadata.new();
|
|
for (var key in metadata) {
|
|
var value = metadata[key];
|
|
generalMetatada.insert(cardano_serialization_lib_nodejs_1.BigNum.from_str(key), Seed.getTransactionMetadatum(value));
|
|
}
|
|
var auxiliaryData = cardano_serialization_lib_nodejs_1.AuxiliaryData.new();
|
|
auxiliaryData.set_metadata(generalMetatada);
|
|
return auxiliaryData;
|
|
};
|
|
Seed.getTransactionMetadatum = function (value) {
|
|
if (value.hasOwnProperty(MetadateTypesEnum.Number)) {
|
|
return cardano_serialization_lib_nodejs_1.TransactionMetadatum.new_int(cardano_serialization_lib_nodejs_1.Int.new(toBigNum(value[MetadateTypesEnum.Number])));
|
|
}
|
|
if (value.hasOwnProperty(MetadateTypesEnum.String)) {
|
|
return cardano_serialization_lib_nodejs_1.TransactionMetadatum.new_text(value[MetadateTypesEnum.String]);
|
|
}
|
|
if (value.hasOwnProperty(MetadateTypesEnum.Bytes)) {
|
|
return cardano_serialization_lib_nodejs_1.TransactionMetadatum.new_bytes(Buffer.from(value[MetadateTypesEnum.Bytes], 'hex'));
|
|
}
|
|
if (value.hasOwnProperty(MetadateTypesEnum.List)) {
|
|
var list = value[MetadateTypesEnum.List];
|
|
var metalist = cardano_serialization_lib_nodejs_1.MetadataList.new();
|
|
for (var i = 0; i < list.length; i++) {
|
|
metalist.add(Seed.getTransactionMetadatum(list[i]));
|
|
}
|
|
return cardano_serialization_lib_nodejs_1.TransactionMetadatum.new_list(metalist);
|
|
}
|
|
if (value.hasOwnProperty(MetadateTypesEnum.Map)) {
|
|
var map = value[MetadateTypesEnum.Map];
|
|
var metamap = cardano_serialization_lib_nodejs_1.MetadataMap.new();
|
|
for (var i = 0; i < map.length; i++) {
|
|
var _a = map[i], k = _a.k, v = _a.v;
|
|
metamap.insert(Seed.getTransactionMetadatum(k), Seed.getTransactionMetadatum(v));
|
|
}
|
|
return cardano_serialization_lib_nodejs_1.TransactionMetadatum.new_map(metamap);
|
|
}
|
|
};
|
|
Seed.generateKeyPair = function () {
|
|
var prvKey = cardano_serialization_lib_nodejs_1.Bip32PrivateKey.generate_ed25519_bip32();
|
|
var pubKey = prvKey.to_public();
|
|
var pair = {
|
|
privateKey: prvKey,
|
|
publicKey: pubKey
|
|
};
|
|
return pair;
|
|
};
|
|
Seed.generateBip32PrivateKey = function () {
|
|
return cardano_serialization_lib_nodejs_1.Bip32PrivateKey.generate_ed25519_bip32();
|
|
};
|
|
// enterprise address without staking ability, for use by exchanges/etc
|
|
Seed.getEnterpriseAddress = function (pubKey, network) {
|
|
if (network === void 0) { network = 'mainnet'; }
|
|
var networkId = network == 'mainnet'
|
|
? cardano_serialization_lib_nodejs_1.NetworkInfo.mainnet().network_id()
|
|
: cardano_serialization_lib_nodejs_1.NetworkInfo.testnet().network_id();
|
|
return cardano_serialization_lib_nodejs_1.EnterpriseAddress.new(networkId, cardano_serialization_lib_nodejs_1.StakeCredential.from_keyhash(pubKey.to_raw_key().hash())).to_address();
|
|
};
|
|
Seed.getKeyHash = function (key) {
|
|
return key.to_raw_key().hash();
|
|
};
|
|
Seed.buildSingleIssuerScript = function (keyHash) {
|
|
var scriptPubKey = cardano_serialization_lib_nodejs_1.ScriptPubkey.new(keyHash);
|
|
return cardano_serialization_lib_nodejs_1.NativeScript.new_script_pubkey(scriptPubKey);
|
|
};
|
|
Seed.buildMultiIssuerAllScript = function (scripts) {
|
|
var nativeScripts = this.buildNativeScripts(scripts);
|
|
var scriptAll = cardano_serialization_lib_nodejs_1.ScriptAll.new(nativeScripts);
|
|
return cardano_serialization_lib_nodejs_1.NativeScript.new_script_all(scriptAll);
|
|
};
|
|
Seed.buildMultiIssuerAnyScript = function (scripts) {
|
|
var nativeScripts = this.buildNativeScripts(scripts);
|
|
var scriptAny = cardano_serialization_lib_nodejs_1.ScriptAny.new(nativeScripts);
|
|
return cardano_serialization_lib_nodejs_1.NativeScript.new_script_any(scriptAny);
|
|
};
|
|
Seed.buildMultiIssuerAtLeastScript = function (n, scripts) {
|
|
var nativeScripts = this.buildNativeScripts(scripts);
|
|
var scriptAtLeast = cardano_serialization_lib_nodejs_1.ScriptNOfK.new(n, nativeScripts);
|
|
return cardano_serialization_lib_nodejs_1.NativeScript.new_script_n_of_k(scriptAtLeast);
|
|
};
|
|
// you need to set validity range on transcation builder to check on a deterministic way
|
|
Seed.buildAfterScript = function (slot) {
|
|
var scriptAfter = cardano_serialization_lib_nodejs_1.TimelockStart.new(slot);
|
|
return cardano_serialization_lib_nodejs_1.NativeScript.new_timelock_start(scriptAfter);
|
|
};
|
|
// you need to set validity range on transcation builder to check on a deterministic way
|
|
Seed.buildBeforeScript = function (slot) {
|
|
var scriptBefore = cardano_serialization_lib_nodejs_1.TimelockExpiry.new(slot);
|
|
return cardano_serialization_lib_nodejs_1.NativeScript.new_timelock_expiry(scriptBefore);
|
|
};
|
|
Seed.getNativeScripts = function (script) {
|
|
var result = [];
|
|
var kind = script.root.kind();
|
|
if (kind == 0) {
|
|
// sig
|
|
result.push(script.root);
|
|
}
|
|
else if (kind == 1 || kind == 2 || kind == 3) {
|
|
// all, any and atLeast respectivetly
|
|
result.push.apply(result, script.scripts.map(function (s) { return s.root; }));
|
|
}
|
|
return result;
|
|
};
|
|
Seed.buildNativeScripts = function (scripts) {
|
|
var nativeScripts = cardano_serialization_lib_nodejs_1.NativeScripts.new();
|
|
scripts.forEach(function (script) {
|
|
nativeScripts.add(script);
|
|
});
|
|
return nativeScripts;
|
|
};
|
|
Seed.getScriptHash = function (script) {
|
|
var keyHash = script.hash(cardano_serialization_lib_nodejs_1.ScriptHashNamespace.NativeScript);
|
|
var scriptHash = cardano_serialization_lib_nodejs_1.ScriptHash.from_bytes(keyHash.to_bytes());
|
|
return scriptHash;
|
|
// let credential = StakeCredential.from_keyhash(keyHash);
|
|
// return credential.to_scripthash();
|
|
};
|
|
Seed.getPolicyId = function (scriptHash) {
|
|
return Buffer.from(scriptHash.to_bytes()).toString('hex');
|
|
};
|
|
Seed.getScriptHashFromPolicy = function (policyId) {
|
|
return cardano_serialization_lib_nodejs_1.ScriptHash.from_bytes(Buffer.from(policyId, 'hex'));
|
|
};
|
|
Seed.getMinUtxoValueWithAssets = function (tokenAssets, config, encoding) {
|
|
if (config === void 0) { config = network_config_1.Mainnet; }
|
|
if (encoding === void 0) { encoding = 'utf8'; }
|
|
var assets = cardano_serialization_lib_nodejs_1.Value.new(toBigNum(1000000));
|
|
var multiAsset = cardano_serialization_lib_nodejs_1.MultiAsset.new();
|
|
var groups = tokenAssets.reduce(function (dict, asset) {
|
|
;
|
|
(dict[asset.policy_id] = dict[asset.policy_id] || []).push(asset);
|
|
return dict;
|
|
}, {});
|
|
var _loop_1 = function (policy_id) {
|
|
var scriptHash = Seed.getScriptHashFromPolicy(policy_id);
|
|
var asset = cardano_serialization_lib_nodejs_1.Assets.new();
|
|
groups[policy_id].forEach(function (a) {
|
|
asset.insert(cardano_serialization_lib_nodejs_1.AssetName.new(Buffer.from(a.asset_name, encoding)), toBigNum(a.quantity));
|
|
});
|
|
multiAsset.insert(scriptHash, asset);
|
|
};
|
|
for (var policy_id in groups) {
|
|
_loop_1(policy_id);
|
|
}
|
|
assets.set_multiasset(multiAsset);
|
|
var min = cardano_serialization_lib_nodejs_1.min_ada_required(assets, false, toBigNum(config.protocolParams.utxoCostPerWord));
|
|
return Number.parseInt(min.to_str());
|
|
};
|
|
// static buildMultisigJsonScript(type: ScriptTypeEnum, witnesses: number = 2): JsonScript {
|
|
// if (lock) {
|
|
// return {
|
|
// type: ScriptTypeEnum.All,
|
|
// scripts: [
|
|
// {
|
|
// type: ScriptTypeEnum.Sig
|
|
// },
|
|
// {
|
|
// type: ScriptTypeEnum.Before,
|
|
// lockTime: new Date(lockTime).getTime()
|
|
// }
|
|
// ]
|
|
// }
|
|
// } else {
|
|
// return {type: ScriptTypeEnum.Sig}
|
|
// }
|
|
// }
|
|
Seed.buildScript = function (json, currentSlot) {
|
|
if (json.type === json_script_model_1.ScriptTypeEnum.Sig) {
|
|
// Single Issuer
|
|
var keyPair = void 0; // needed to get the signing keys when export (e.g toJSON)
|
|
var keyHash = void 0;
|
|
if (!json.keyHash) {
|
|
keyPair = Seed.generateKeyPair();
|
|
keyHash = Seed.getKeyHash(keyPair.publicKey);
|
|
}
|
|
else {
|
|
keyHash = cardano_serialization_lib_nodejs_1.Ed25519KeyHash.from_bytes(Buffer.from(json.keyHash, 'hex'));
|
|
}
|
|
return {
|
|
root: Seed.buildSingleIssuerScript(keyHash),
|
|
keyHash: Buffer.from(keyHash.to_bytes()).toString('hex'),
|
|
keyPair: keyPair,
|
|
scripts: []
|
|
};
|
|
}
|
|
if (json.type === json_script_model_1.ScriptTypeEnum.All) {
|
|
// Multiple Issuer All
|
|
var scripts = json.scripts.map(function (s) { return Seed.buildScript(s, currentSlot); });
|
|
return {
|
|
root: Seed.buildMultiIssuerAllScript(scripts.map(function (s) { return s.root; })),
|
|
scripts: scripts
|
|
};
|
|
}
|
|
if (json.type === json_script_model_1.ScriptTypeEnum.Any) {
|
|
// Multiple Issuer Any
|
|
var scripts = json.scripts.map(function (s) { return Seed.buildScript(s, currentSlot); });
|
|
return {
|
|
root: Seed.buildMultiIssuerAnyScript(scripts.map(function (s) { return s.root; })),
|
|
scripts: scripts
|
|
};
|
|
}
|
|
if (json.type === json_script_model_1.ScriptTypeEnum.AtLeast) {
|
|
// Multiple Issuer At least
|
|
var scripts = json.scripts.map(function (s) { return Seed.buildScript(s, currentSlot); });
|
|
var n = json.require;
|
|
return {
|
|
root: Seed.buildMultiIssuerAtLeastScript(n, scripts.map(function (s) { return s.root; })),
|
|
scripts: scripts
|
|
};
|
|
}
|
|
if (json.type === json_script_model_1.ScriptTypeEnum.After) {
|
|
// After
|
|
var slot = 0;
|
|
if (!json.slot) {
|
|
slot = currentSlot; // after now
|
|
var lockTime = json.lockTime;
|
|
if (lockTime != 'now') {
|
|
var now = Date.now();
|
|
var datetime = new Date(lockTime).getTime();
|
|
slot = currentSlot + Math.floor((datetime - now) / 1000);
|
|
}
|
|
}
|
|
else {
|
|
slot = json.slot;
|
|
}
|
|
return { root: Seed.buildAfterScript(slot), slot: slot, scripts: [] };
|
|
}
|
|
if (json.type === json_script_model_1.ScriptTypeEnum.Before) {
|
|
// Before
|
|
var slot = 0;
|
|
if (!json.slot) {
|
|
var lockTime = json.lockTime;
|
|
slot = currentSlot + 180; // only 3 min to mint tokens
|
|
if (lockTime != 'now') {
|
|
var now = Date.now();
|
|
var datetime = new Date(lockTime).getTime();
|
|
slot = currentSlot + Math.floor((datetime - now) / 1000);
|
|
}
|
|
}
|
|
else {
|
|
slot = json.slot;
|
|
}
|
|
return { root: Seed.buildBeforeScript(slot), slot: slot, scripts: [] };
|
|
}
|
|
};
|
|
Seed.scriptToJson = function (script) {
|
|
var result = {};
|
|
result.type = json_script_model_1.scriptTypes[script.root.kind()];
|
|
if (script.keyHash) {
|
|
result.keyHash = script.keyHash;
|
|
}
|
|
if (result.type === 'atLeast') {
|
|
// Multiple Issuer At least)
|
|
result.require = script.root.as_script_n_of_k().n();
|
|
}
|
|
if (result.type === 'after' || result.type === 'before') {
|
|
result.slot = script.slot;
|
|
}
|
|
if (script.scripts && script.scripts.length > 0) {
|
|
result.scripts = script.scripts.map(function (s) { return Seed.scriptToJson(s); });
|
|
}
|
|
return result;
|
|
};
|
|
Seed.getScriptKeys = function (script) {
|
|
var result = [];
|
|
if (script.keyPair) {
|
|
// let prvKey = Bip32PrivateKey.from_bech32(script.signingKey);
|
|
// let pubKey = prvKey.to_public();
|
|
// result.push({ publicKey: pubKey, privateKey: prvKey});
|
|
result.push(script.keyPair.privateKey);
|
|
}
|
|
script.scripts.forEach(function (s) {
|
|
result.push.apply(result, Seed.getScriptKeys(s));
|
|
});
|
|
return result;
|
|
};
|
|
Seed.getScriptAddress = function (script, network) {
|
|
if (network === void 0) { network = 'mainnet'; }
|
|
var networkId = network == 'mainnet'
|
|
? cardano_serialization_lib_nodejs_1.NetworkInfo.mainnet().network_id()
|
|
: cardano_serialization_lib_nodejs_1.NetworkInfo.testnet().network_id();
|
|
var scriptHash = this.getScriptHash(script.root);
|
|
var credential = cardano_serialization_lib_nodejs_1.StakeCredential.from_scripthash(scriptHash);
|
|
return cardano_serialization_lib_nodejs_1.BaseAddress.new(networkId, credential, credential).to_address();
|
|
};
|
|
Seed.getPolicyScriptId = function (script) {
|
|
var scriptHash = Seed.getScriptHash(script.root);
|
|
return Buffer.from(scriptHash.to_bytes()).toString('hex');
|
|
};
|
|
Seed.findSlots = function (script) {
|
|
var result = {};
|
|
var type = script.root.kind();
|
|
if (type === 4) {
|
|
//after
|
|
result.start = script.slot;
|
|
}
|
|
else if (type === 5) {
|
|
//before
|
|
result.end = script.slot;
|
|
}
|
|
else {
|
|
var slots = script.scripts.map(function (s) { return Seed.findSlots(s); });
|
|
result.start = slots.reduce(function (max, act) { return (!act.start && !max ? max : Math.max(act.start, max)); }, result.start);
|
|
result.end = slots.reduce(function (min, act) {
|
|
return !act.end ? min : !min ? act.end : Math.min(act.end, min);
|
|
}, result.end);
|
|
}
|
|
return result;
|
|
};
|
|
Seed.isInteger = function (value) {
|
|
return Number.isInteger(Number(value));
|
|
};
|
|
return Seed;
|
|
}());
|
|
exports.Seed = Seed;
|
|
function toBigNum(quantity) {
|
|
return cardano_serialization_lib_nodejs_1.BigNum.from_str(quantity.toString());
|
|
}
|
|
var Bip32KeyPair = /** @class */ (function () {
|
|
function Bip32KeyPair() {
|
|
}
|
|
return Bip32KeyPair;
|
|
}());
|
|
exports.Bip32KeyPair = Bip32KeyPair;
|
|
var MetadateTypesEnum;
|
|
(function (MetadateTypesEnum) {
|
|
MetadateTypesEnum["Number"] = "int";
|
|
MetadateTypesEnum["String"] = "string";
|
|
MetadateTypesEnum["Bytes"] = "bytes";
|
|
MetadateTypesEnum["List"] = "list";
|
|
MetadateTypesEnum["Map"] = "map";
|
|
})(MetadateTypesEnum = exports.MetadateTypesEnum || (exports.MetadateTypesEnum = {}));
|
|
exports.CARDANO_PUROPOSE = 1852;
|
|
exports.CARDANO_COIN_TYPE = 1815;
|
|
exports.CARDANO_EXTERNAL = 0;
|
|
exports.CARDANO_CHANGE = 1;
|
|
exports.CARDANO_CHIMERIC = 2;
|
|
//# sourceMappingURL=utils.js.map
|