@hover-labs/tezos-msig-cli
Version:
CLI Client for Tezos timelock multisig.
228 lines • 16.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.execute = exports.submit = exports.rotateKey = exports.cancel = exports.deployMultisig = exports.cancelbytesToSubmit = exports.keyRotationbytesToSubmit = exports.bytesToSubmit = void 0;
const tezos_multisig_lib_1 = require("@hover-labs/tezos-multisig-lib");
const conseiljs_1 = require("conseiljs");
const helpers_1 = require("./helpers");
const CONTRACT_SOURCE = `${__dirname}/msig-timelock.tz`;
const bytesToSubmit = async (operation, nodeUrl, operationId, multiSigContractAddress, attemptAutomatic, smartpyPath) => {
const chainId = await tezos_multisig_lib_1.getChainId(nodeUrl);
const actualOperationId = operationId
? operationId
: (await tezos_multisig_lib_1.getOperationId(multiSigContractAddress, nodeUrl)) + 1;
const lambda = tezos_multisig_lib_1.compileOperation(operation, smartpyPath);
const michelson = `Pair "${chainId}" (Pair ${actualOperationId} ${lambda})`;
tezos_multisig_lib_1.Utils.print('Data to encode');
tezos_multisig_lib_1.Utils.print(`Pair "${chainId}" (Pair ${actualOperationId} ${lambda})'`);
tezos_multisig_lib_1.Utils.print(``);
tezos_multisig_lib_1.Utils.print('Encode bytes with: ');
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} hash data 'Pair "${chainId}" (Pair ${actualOperationId} ${lambda})' of type 'pair chain_id (pair nat (lambda unit (list operation)))'`);
tezos_multisig_lib_1.Utils.print('');
tezos_multisig_lib_1.Utils.print(`Verify these bytes with: `);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} unpack michelson data 0x<BYTES>`);
tezos_multisig_lib_1.Utils.print('');
tezos_multisig_lib_1.Utils.print(`Sign these bytes with: `);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} sign bytes 0x<BYTES> for <KEY>`);
tezos_multisig_lib_1.Utils.print('');
if (attemptAutomatic) {
const hex = conseiljs_1.TezosMessageUtils.writePackedData(michelson, 'pair (chain_id) (pair (nat) (lambda unit (list operation)))', conseiljs_1.TezosParameterFormat.Michelson);
tezos_multisig_lib_1.Utils.print(`[Experimental] I tried to encode the bytes myself. Here is what I came up with: `);
tezos_multisig_lib_1.Utils.print(hex);
tezos_multisig_lib_1.Utils.print('');
}
};
exports.bytesToSubmit = bytesToSubmit;
const keyRotationbytesToSubmit = async (threshold, keyList, nodeUrl, operationId, multiSigContractAddress, attemptAutomatic) => {
const chainId = await tezos_multisig_lib_1.getChainId(nodeUrl);
const actualOperationId = operationId
? operationId
: (await tezos_multisig_lib_1.getOperationId(multiSigContractAddress, nodeUrl)) + 1;
const keyListMichelson = keyList.reduce((previous, current) => {
return `${previous} "${current}";`;
}, '');
const michelson = `Pair "${chainId}" (Pair ${actualOperationId} (Pair ${threshold} {${keyListMichelson}}))`;
tezos_multisig_lib_1.Utils.print('Data to encode');
tezos_multisig_lib_1.Utils.print(`${michelson}`);
tezos_multisig_lib_1.Utils.print(``);
tezos_multisig_lib_1.Utils.print('Encode bytes with: ');
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} hash data '${michelson}' of type 'pair chain_id (pair nat (pair nat (list key)))'`);
tezos_multisig_lib_1.Utils.print('');
tezos_multisig_lib_1.Utils.print(`Verify these bytes with: `);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} unpack michelson data 0x<BYTES>`);
tezos_multisig_lib_1.Utils.print('');
tezos_multisig_lib_1.Utils.print(`Sign these bytes with: `);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} sign bytes 0x<BYTES> for <KEY>`);
tezos_multisig_lib_1.Utils.print('');
if (attemptAutomatic) {
const hex = conseiljs_1.TezosMessageUtils.writePackedData(michelson, 'pair chain_id (pair nat (pair nat (list key)))', conseiljs_1.TezosParameterFormat.Michelson);
tezos_multisig_lib_1.Utils.print(`[Experimental] I tried to encode the bytes myself. Here is what I came up with: `);
tezos_multisig_lib_1.Utils.print(hex);
tezos_multisig_lib_1.Utils.print('');
}
};
exports.keyRotationbytesToSubmit = keyRotationbytesToSubmit;
const cancelbytesToSubmit = async (operationIdToCancel, nodeUrl, operationId, multiSigContractAddress, attemptAutomatic) => {
const chainId = await tezos_multisig_lib_1.getChainId(nodeUrl);
const actualOperationId = operationId
? operationId
: (await tezos_multisig_lib_1.getOperationId(multiSigContractAddress, nodeUrl)) + 1;
const michelson = `Pair "${chainId}" (Pair ${actualOperationId} ${operationIdToCancel})`;
tezos_multisig_lib_1.Utils.print('Data to encode');
tezos_multisig_lib_1.Utils.print(`${michelson}`);
tezos_multisig_lib_1.Utils.print(``);
tezos_multisig_lib_1.Utils.print('Encode bytes with: ');
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} hash data '${michelson}' of type 'pair chain_id (pair nat nat)'`);
tezos_multisig_lib_1.Utils.print('');
tezos_multisig_lib_1.Utils.print(`Verify these bytes with: `);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} unpack michelson data 0x<BYTES>`);
tezos_multisig_lib_1.Utils.print('');
tezos_multisig_lib_1.Utils.print(`Sign these bytes with: `);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} sign bytes 0x<BYTES> for <KEY>`);
tezos_multisig_lib_1.Utils.print('');
if (attemptAutomatic) {
const hex = conseiljs_1.TezosMessageUtils.writePackedData(michelson, 'pair chain_id (pair nat nat)', conseiljs_1.TezosParameterFormat.Michelson);
tezos_multisig_lib_1.Utils.print(`[Experimental] I tried to encode the bytes myself. Here is what I came up with: `);
tezos_multisig_lib_1.Utils.print(hex);
tezos_multisig_lib_1.Utils.print('');
}
};
exports.cancelbytesToSubmit = cancelbytesToSubmit;
const deployMultisig = async (timelockSeconds, threshold, publicKeys, nodeUrl, privateKey) => {
const source = tezos_multisig_lib_1.loadContract(CONTRACT_SOURCE);
const sortedPublicKeys = publicKeys.sort();
const michelsonPublicKeyList = sortedPublicKeys.reduce((previous, current) => {
return `${previous} "${current}"`;
}, '');
const storage = `(Pair(Pair 0 { ${michelsonPublicKeyList}}) (Pair ${threshold} (Pair { } ${timelockSeconds})))`;
const keyStore = await helpers_1.keyStoreFromPrivateKey(privateKey);
const signer = await tezos_multisig_lib_1.Utils.signerFromKeyStore(keyStore);
tezos_multisig_lib_1.Utils.print(`Deploying from: ${keyStore.publicKeyHash} `);
tezos_multisig_lib_1.Utils.print(`Storage: ${storage} `);
await tezos_multisig_lib_1.Utils.revealAccountIfNeeded(nodeUrl, keyStore, signer);
let counter = await conseiljs_1.TezosNodeReader.getCounterForAccount(nodeUrl, keyStore.publicKeyHash);
counter++;
const deployResult = await tezos_multisig_lib_1.deployContract(nodeUrl, source, storage, keyStore, counter);
tezos_multisig_lib_1.Utils.print(`Deployed!`);
tezos_multisig_lib_1.Utils.print(`Address: ${deployResult.contractAddress} `);
tezos_multisig_lib_1.Utils.print(`Operation Hash: ${deployResult.operationHash} `);
};
exports.deployMultisig = deployMultisig;
const cancel = async (operationIdToCancel, addresses, signatures, operationId, multiSigContractAddress, nodeUrl, privateKey, attemptAutomatic) => {
const keyStore = await helpers_1.keyStoreFromPrivateKey(privateKey);
const signer = await tezos_multisig_lib_1.Utils.signerFromKeyStore(keyStore);
const actualOperationId = operationId
? operationId
: (await tezos_multisig_lib_1.getOperationId(multiSigContractAddress, nodeUrl)) + 1;
tezos_multisig_lib_1.Utils.print(`Submitting cancel operation from: ${keyStore.publicKeyHash} `);
tezos_multisig_lib_1.Utils.print(`Using operation ID: ${actualOperationId} `);
await tezos_multisig_lib_1.Utils.revealAccountIfNeeded(nodeUrl, keyStore, signer);
const counter = await conseiljs_1.TezosNodeReader.getCounterForAccount(nodeUrl, keyStore.publicKeyHash);
const chainId = await tezos_multisig_lib_1.getChainId(nodeUrl);
let signaturesMap = '';
for (let i = 0; i < addresses.length; i++) {
const address = addresses[i];
const signature = signatures[i];
signaturesMap += `Elt "${address}" "${signature}"; `;
}
const param = `Pair { ${signaturesMap} } (Pair "${chainId}" (Pair ${actualOperationId} ${operationIdToCancel}))`;
tezos_multisig_lib_1.Utils.print(`Use tezos-client to submit the operation manually.`);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} transfer 0 from ${keyStore.publicKeyHash} to ${multiSigContractAddress} --arg '${param}' --entrypoint 'cancel'`);
tezos_multisig_lib_1.Utils.print('');
if (attemptAutomatic) {
tezos_multisig_lib_1.Utils.print(`Attempting to inject automatically:`);
const operation = conseiljs_1.TezosNodeWriter.constructContractInvocationOperation(keyStore.publicKeyHash, counter + 1, multiSigContractAddress, 0, 0, tezos_multisig_lib_1.Constants.storageLimit, tezos_multisig_lib_1.Constants.gasLimit, 'cancel', `${param} `, conseiljs_1.TezosParameterFormat.Michelson);
const operationFeeEstimator = new tezos_multisig_lib_1.OperationFeeEstimator(nodeUrl);
const operationsWithFees = await operationFeeEstimator.estimateAndApplyFees([operation]);
const nodeResult = await conseiljs_1.TezosNodeWriter.sendOperation(nodeUrl, operationsWithFees, signer);
const hash = nodeResult.operationGroupID.replace(/"/g, '');
tezos_multisig_lib_1.Utils.print(`Executed with hash: ${hash} `);
}
};
exports.cancel = cancel;
const rotateKey = async (threshold, keyList, addresses, signatures, operationId, multiSigContractAddress, nodeUrl, privateKey, attemptAutomatic) => {
const keyStore = await helpers_1.keyStoreFromPrivateKey(privateKey);
const signer = await tezos_multisig_lib_1.Utils.signerFromKeyStore(keyStore);
const actualOperationId = operationId
? operationId
: (await tezos_multisig_lib_1.getOperationId(multiSigContractAddress, nodeUrl)) + 1;
tezos_multisig_lib_1.Utils.print(`Submitting rotate from: ${keyStore.publicKeyHash} `);
tezos_multisig_lib_1.Utils.print(`Using operation ID: ${actualOperationId} `);
await tezos_multisig_lib_1.Utils.revealAccountIfNeeded(nodeUrl, keyStore, signer);
const counter = await conseiljs_1.TezosNodeReader.getCounterForAccount(nodeUrl, keyStore.publicKeyHash);
const chainId = await tezos_multisig_lib_1.getChainId(nodeUrl);
const keyListMichelson = keyList.reduce((previous, current) => {
return `${previous} "${current}";`;
}, '');
let signaturesMap = '';
for (let i = 0; i < addresses.length; i++) {
const address = addresses[i];
const signature = signatures[i];
signaturesMap += `Elt "${address}" "${signature}"; `;
}
const param = `Pair { ${signaturesMap} } (Pair "${chainId}" (Pair ${actualOperationId} (Pair ${threshold} {${keyListMichelson}})))`;
tezos_multisig_lib_1.Utils.print(`Use tezos-client to submit the operation manually.`);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} transfer 0 from ${keyStore.publicKeyHash} to ${multiSigContractAddress} --arg '${param}' --entrypoint 'rotate'`);
tezos_multisig_lib_1.Utils.print('');
if (attemptAutomatic) {
tezos_multisig_lib_1.Utils.print(`Attempting to inject automatically:`);
const operation = conseiljs_1.TezosNodeWriter.constructContractInvocationOperation(keyStore.publicKeyHash, counter + 1, multiSigContractAddress, 0, 0, tezos_multisig_lib_1.Constants.storageLimit, tezos_multisig_lib_1.Constants.gasLimit, 'rotate', `${param} `, conseiljs_1.TezosParameterFormat.Michelson);
const operationFeeEstimator = new tezos_multisig_lib_1.OperationFeeEstimator(nodeUrl);
const operationsWithFees = await operationFeeEstimator.estimateAndApplyFees([operation]);
const nodeResult = await conseiljs_1.TezosNodeWriter.sendOperation(nodeUrl, operationsWithFees, signer);
const hash = nodeResult.operationGroupID.replace(/"/g, '');
tezos_multisig_lib_1.Utils.print(`Executed with hash: ${hash} `);
}
};
exports.rotateKey = rotateKey;
const submit = async (operation, addresses, signatures, operationId, multiSigContractAddress, nodeUrl, privateKey, attemptAutomatic, smartpyPath) => {
const keyStore = await helpers_1.keyStoreFromPrivateKey(privateKey);
const signer = await tezos_multisig_lib_1.Utils.signerFromKeyStore(keyStore);
tezos_multisig_lib_1.Utils.print(`Submitting operation from: ${keyStore.publicKeyHash} `);
tezos_multisig_lib_1.Utils.print(`Using operation ID: ${operationId} `);
await tezos_multisig_lib_1.Utils.revealAccountIfNeeded(nodeUrl, keyStore, signer);
const actualOperationId = operationId
? operationId
: (await tezos_multisig_lib_1.getOperationId(multiSigContractAddress, nodeUrl)) + 1;
tezos_multisig_lib_1.Utils.print(`Using operation ID: ${actualOperationId} `);
const counter = await conseiljs_1.TezosNodeReader.getCounterForAccount(nodeUrl, keyStore.publicKeyHash);
const chainId = await tezos_multisig_lib_1.getChainId(nodeUrl);
const lambda = tezos_multisig_lib_1.compileOperation(operation, smartpyPath);
let signaturesMap = '';
for (let i = 0; i < addresses.length; i++) {
const address = addresses[i];
const signature = signatures[i];
signaturesMap += `Elt "${address}" "${signature}"; `;
}
const param = `Pair { ${signaturesMap} } (Pair "${chainId}" (Pair ${actualOperationId} ${lambda}))`;
tezos_multisig_lib_1.Utils.print(`Use tezos-client to submit the operation manually.`);
tezos_multisig_lib_1.Utils.print(`tezos-client -E ${nodeUrl} transfer 0 from ${keyStore.publicKeyHash} to ${multiSigContractAddress} --arg '${param}' --entrypoint 'submit'`);
tezos_multisig_lib_1.Utils.print('');
if (attemptAutomatic) {
tezos_multisig_lib_1.Utils.print(`Attempting to inject automatically:`);
const operation = conseiljs_1.TezosNodeWriter.constructContractInvocationOperation(keyStore.publicKeyHash, counter + 1, multiSigContractAddress, 0, 0, tezos_multisig_lib_1.Constants.storageLimit, tezos_multisig_lib_1.Constants.gasLimit, 'submit', `${param} `, conseiljs_1.TezosParameterFormat.Michelson);
const operationFeeEstimator = new tezos_multisig_lib_1.OperationFeeEstimator(nodeUrl);
const operationsWithFees = await operationFeeEstimator.estimateAndApplyFees([operation]);
const nodeResult = await conseiljs_1.TezosNodeWriter.sendOperation(nodeUrl, operationsWithFees, signer);
const hash = nodeResult.operationGroupID.replace(/"/g, '');
tezos_multisig_lib_1.Utils.print(`Executed with hash: ${hash} `);
}
};
exports.submit = submit;
const execute = async (operationId, multiSigContractAddress, nodeUrl, privateKey) => {
const keyStore = await helpers_1.keyStoreFromPrivateKey(privateKey);
const signer = await tezos_multisig_lib_1.Utils.signerFromKeyStore(keyStore);
tezos_multisig_lib_1.Utils.print(`Sending execute from: ${keyStore.publicKeyHash} `);
tezos_multisig_lib_1.Utils.print(`Using operation ID: ${operationId} `);
await tezos_multisig_lib_1.Utils.revealAccountIfNeeded(nodeUrl, keyStore, signer);
const counter = await conseiljs_1.TezosNodeReader.getCounterForAccount(nodeUrl, keyStore.publicKeyHash);
const operation = conseiljs_1.TezosNodeWriter.constructContractInvocationOperation(keyStore.publicKeyHash, counter + 1, multiSigContractAddress, 0, 0, tezos_multisig_lib_1.Constants.storageLimit, tezos_multisig_lib_1.Constants.gasLimit, 'execute', `${operationId} `, conseiljs_1.TezosParameterFormat.Michelson);
const operationFeeEstimator = new tezos_multisig_lib_1.OperationFeeEstimator(nodeUrl);
const operationsWithFees = await operationFeeEstimator.estimateAndApplyFees([
operation,
]);
const nodeResult = await conseiljs_1.TezosNodeWriter.sendOperation(nodeUrl, operationsWithFees, signer);
const hash = nodeResult.operationGroupID.replace(/"/g, '');
tezos_multisig_lib_1.Utils.print(`Executed with hash: ${hash} `);
};
exports.execute = execute;
//# sourceMappingURL=commands.js.map