PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-xtz/src/lib
Просмотр файла: multisigUtils.ts
import * as _ from 'lodash';
import { IndexedSignature, OriginationData, OriginationOp, RevealOp, TransactionOp, TransferData } from './iface';
import { DEFAULT_FEE, DEFAULT_GAS_LIMIT, DEFAULT_STORAGE_LIMIT, hashTypes, isValidKey } from './utils';
// Default n of m for multisig wallets
const DEFAULT_N = 2;
const DEFAULT_M = 3;
/**
* Helper method to get the transfer details from a generic multisig transaction operation.
*
* @param {TransactionOp} operation A transaction operation JSON
* @returns {TransferData} Information about the destination, token and transfer amount
*/
export function getMultisigTransferDataFromOperation(operation: TransactionOp): TransferData {
const fee = {
fee: operation.fee,
gasLimit: operation.gas_limit,
storageLimit: operation.storage_limit,
};
if (!operation.parameters) {
// Singlesig transaction
return {
coin: 'mutez',
from: operation.source,
to: operation.destination,
amount: operation.amount,
fee,
};
}
// These follow the structure from the response of genericMultisigTransferParams()
const transferArgs = operation.parameters.value.args[0].args[1].args[0];
const accountType = transferArgs[3].prim;
const counter = operation.parameters.value.args[0].args[0].int;
// In multisig transactions, the wallet contract is the destination
const from = operation.destination;
let accountTypeIndex;
switch (accountType) {
case 'IMPLICIT_ACCOUNT':
accountTypeIndex = 4;
break;
case 'CONTRACT':
accountTypeIndex = 5;
break;
default:
throw new Error('Invalid contract parameters');
}
return {
coin: transferArgs[accountTypeIndex].args[0].prim,
from,
to: transferArgs[2].args[1].string,
amount: transferArgs[accountTypeIndex].args[1].int,
fee,
counter,
};
}
/**
* Helper method to get the wallet or address initialization tx from an origination operation
*
* @param {OriginationOp} operation
* @returns {OriginationData} Information about the wallet contract creating a forwarder contract
*/
export function getOriginationDataFromOperation(operation: OriginationOp): OriginationData {
const fee = {
fee: operation.fee,
gasLimit: operation.gas_limit,
storageLimit: operation.storage_limit,
};
const { source: from, counter, balance } = operation;
// Transactions initializing a forwarder contract contain the address of the wallet contract
const forwarderDestination: string = _.get(operation, 'script.code[2].args[0][3].args[0][0].args[1].string');
return {
fee,
counter,
balance,
from,
forwarderDestination,
};
}
/**
* Helper method to build a singlesig transaction operation.
*
* @param {string} counter Source account next counter
* @param {string} source The account that will pay for fees, and in singlesig transactions, where
* the funds are taken from
* @param {string} amount The amount in mutez to be transferred
* @param {string} destination The account address to send the funds to
* @param {string} fee Fees in mutez to pay by the source account
* @param {string} gasLimit Maximum amount in mutez to spend in gas fees
* @param {string} storageLimit Maximum amount in mutez to spend in storage fees
* @returns {TransactionOp}A Tezos transaction operation
*/
export function singlesigTransactionOperation(
counter: string,
source: string,
amount: string,
destination: string,
fee: string = DEFAULT_FEE.TRANSFER.toString(),
gasLimit: string = DEFAULT_GAS_LIMIT.TRANSFER.toString(),
storageLimit: string = DEFAULT_STORAGE_LIMIT.TRANSFER.toString()
): TransactionOp {
return {
kind: 'transaction',
source,
fee,
counter,
gas_limit: gasLimit,
storage_limit: storageLimit,
amount,
destination,
};
}
/**
* Create a multisig wallet transaction operation.
*
* @see {@link transactionOperation}
* @param {string} counter Source account next counter
* @param {string} source The account that will pay for fees, and in singlesig transactions, where
* the funds are taken from
* @param {string} amount The amount in mutez to be transferred
* @param {string} contractAddress If it is a multisig transfer, the smart contract address with the
* funds to be transferred from
* @param {string} contractCounter If it is a multisig transfer, the smart contract counter to use
* in the next transaction
* @param {string} destinationAddress An implicit or originated address to transfer fudns to
* @param {string[]} signatures signatures List of signatures authorizing the funds transfer form
* the multisig wallet
* @param {string} fee Fees in mutez to pay by the source account
* @param {string} gasLimit Maximum amount in mutez to spend in gas fees
* @param {string} storageLimit Maximum amount in mutez to spend in storage fees
* @param {number} m The number of signers (owners) for the multisig wallet being used. Default is 3
* @returns {TransactionOp} A Tezos operation with a generic multisig transfer
*/
export function multisigTransactionOperation(
counter: string,
source: string,
amount: string,
contractAddress: string,
contractCounter: string,
destinationAddress: string,
signatures: IndexedSignature[],
fee: string = DEFAULT_FEE.TRANSFER.toString(),
gasLimit: string = DEFAULT_GAS_LIMIT.TRANSFER.toString(),
storageLimit: string = DEFAULT_STORAGE_LIMIT.TRANSFER.toString(),
m: number = DEFAULT_M
): TransactionOp {
return {
kind: 'transaction',
source,
fee,
counter,
gas_limit: gasLimit,
storage_limit: storageLimit,
amount: '0', // Don't transfer any funds from he source account to the contract in multisig txs
destination: contractAddress,
parameters: genericMultisigTransferParams(destinationAddress, amount, contractCounter, signatures, m),
};
}
/**
* Helper function to build the parameters to call the generic multisig smart contract with.
*
* @param {string} destinationAddress An implicit or originated address
* @param {number} amount Number of Mutez to be transferred
* @param {string} contractCounter Multisig contract counter number
* @param {IndexedSignature[]} signatures List of transactions and their order
* @param {number} m The multisig wallet total number of signers (owners)
* @returns The parameters object
*/
function genericMultisigTransferParams(
destinationAddress: string,
amount: string,
contractCounter: string,
signatures: IndexedSignature[],
m: number
) {
const transactionSignatures: any[] = buildSignatures(signatures);
return {
entrypoint: 'main',
value: {
prim: 'Pair',
args: [
{
prim: 'Pair',
args: [{ int: contractCounter }, { prim: 'Left', args: [transferToAccount(destinationAddress, amount)] }],
},
transactionSignatures,
],
},
};
}
/**
* Replace the signatures in a multisig transaction operation with new ones.
*
* @param {TransactionOp} transaction Transaction to mutate
* @param {IndexedSignature[]} signatures List of transactions and their order
*/
export function updateMultisigTransferSignatures(transaction: TransactionOp, signatures: IndexedSignature[]) {
transaction.parameters.value.args[1] = buildSignatures(signatures, transaction.parameters.value.args[1]);
}
/**
* Ge the list if multisig signatures if any in a convenient format.
*
* @param {TransactionOp} transaction The transaction to search the signatures in
* @returns {IndexedSignature[]} A list of signatures and their order in teh transfer script
*/
export function getMultisigTransferSignatures(transaction: TransactionOp): IndexedSignature[] {
const signatures: IndexedSignature[] = [];
if (!transaction.parameters && !transaction.parameters.value && !transaction.parameters.value) {
return [];
}
const rawSignatures = transaction.parameters.value.args[1];
for (let i = 0; i < rawSignatures.length; i++) {
if (rawSignatures[i].prim === 'Some') {
signatures.push({
signature: rawSignatures[i].args[0].string,
index: i,
});
}
}
return signatures;
}
/**
* Build a list of ordered signatures, putting a None primitive for the missing indexes.
*
* @param {IndexedSignature[]} signatures List of transactions and their order
* @param {number} m Size of the signature list
* @param {any[]} existingSignatures List of existing signatures to merge with the generated ones
* @returns {any[]} List of signatures in the right order
*/
function buildSignatures(signatures: IndexedSignature[], existingSignatures = [], m: number = DEFAULT_M) {
// Initialize the array with the existing signatures and/or empty objects
const transactionSignatures: any[] = existingSignatures;
const size = existingSignatures.length;
if (size > m) {
throw new Error('Too many signatures. Expected less than ' + m + ' got ' + size);
}
for (let i = size; i < m; i++) {
transactionSignatures.push({ prim: 'None' });
}
// Replace the empty signatures for the real ones based on the right index
signatures.forEach((s) => {
if (s.index) {
transactionSignatures[s.index] = { prim: 'Some', args: [{ string: s.signature }] };
} else {
for (let i = 0; i < transactionSignatures.length; i++) {
// Search for the first "null" signature
if (transactionSignatures[i].prim === 'None') {
transactionSignatures[i] = { prim: 'Some', args: [{ string: s.signature }] };
break;
}
}
}
});
return transactionSignatures;
}
/**
* Helper function to build the Michelson script to be signed to transfer funds from a multisig
* wallet.
*
* @param contractAddress The multisig smart contract address
* @param {string} destinationAddress The destination account address (implicit or originated)
* @param {number} amount Number of mutez to transfer
* @param {string} contractCounter Wallet counter to use in the transaction
* @returns A JSON representation of the Michelson script to sign and approve a transfer
*/
export function genericMultisigDataToSign(
contractAddress: string,
destinationAddress: string,
amount: string,
contractCounter: string
) {
const data = {
prim: 'Pair',
args: [
{ int: contractCounter },
{
prim: 'Left',
args: [transferToAccount(destinationAddress, amount)],
},
],
};
const type = {
prim: 'pair',
args: [
{
prim: 'nat',
annots: ['%counter'],
},
{
prim: 'or',
args: [
{
prim: 'lambda',
args: [
{ prim: 'unit' },
{
prim: 'list',
args: [{ prim: 'operation' }],
},
],
annots: ['%operation'],
},
{
prim: 'pair',
args: [
{
prim: 'nat',
annots: ['%threshold'],
},
{
prim: 'list',
args: [{ prim: 'key' }],
annots: ['%keys'],
},
],
annots: ['%change_keys'],
},
],
annots: [':action'],
},
],
annots: [':payload'],
};
return buildPair(data, type, contractAddress);
}
/**
* Util function to build a Michelson Pair object.
*
* @param data
* @param type
* @param contractAddress
*/
function buildPair(data: any, type: any, contractAddress: any) {
return {
data: {
prim: 'Pair',
args: [{ string: contractAddress }, data],
},
type: {
prim: 'pair',
args: [{ prim: 'address' }, type],
},
};
}
/**
* Build the lambda for the multisig transaction transfer to an implicit or originated account.
*
* @param {string} address Account address to send the funds to
* @param {string} amount The amount in mutez to transfer
* @see {@link https://tezostaquito.io/docs/making_transfers#transfer-000005-50-mutez-tokens-from-a-kt1-address-to-a-tz1-address}
*/
function transferToAccount(address: string, amount: string) {
if (isValidKey(address, hashTypes.KT)) {
return transferToOriginatedAccount(address, amount);
}
// Lambda to transfer to an implicit account
return [
{ prim: 'DROP' },
{ prim: 'NIL', args: [{ prim: 'operation' }] },
{
prim: 'PUSH',
args: [{ prim: 'key_hash' }, { string: address }],
},
{ prim: 'IMPLICIT_ACCOUNT' },
{
prim: 'PUSH',
args: [{ prim: 'mutez' }, { int: amount }],
},
{ prim: 'UNIT' },
{ prim: 'TRANSFER_TOKENS' },
{ prim: 'CONS' },
];
}
/**
* Build the lambda for the multisig transaction transfer to an originated account.
*
* @param {string} address Originated account address to send the funds to
* @param {string} amount The amount in mutez to transfer
* @see {@link https://tezostaquito.io/docs/making_transfers#transfer-0000001-1-mutez-tokens-from-a-kt1-address-to-a-kt1-address}
*/
function transferToOriginatedAccount(address: string, amount: string) {
return [
{ prim: 'DROP' },
{ prim: 'NIL', args: [{ prim: 'operation' }] },
{
prim: 'PUSH',
args: [{ prim: 'address' }, { string: address }],
},
{ prim: 'CONTRACT', args: [{ prim: 'unit' }] },
[
{
prim: 'IF_NONE',
args: [[[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]], []],
},
],
{
prim: 'PUSH',
args: [{ prim: 'mutez' }, { int: amount }],
},
{ prim: 'UNIT' },
{ prim: 'TRANSFER_TOKENS' },
{ prim: 'CONS' },
];
}
/**
* Create a reveal operation for a public key.
*
* @param {string} counter Source account next counter
* @param {string} source Source account address
* @param {string} pubKey The public key to reveal
* @param {string} fee Fees in mutez to pay by the source account
* @param {string} gasLimit Maximum amount in mutez to spend in gas fees
* @param {string} storageLimit Maximum amount in mutez to spend in storage fees
* @returns An origination operation
*/
export function revealOperation(
counter: string,
source: string,
pubKey: string,
fee: string = DEFAULT_FEE.REVEAL.toString(),
gasLimit: string = DEFAULT_GAS_LIMIT.REVEAL.toString(),
storageLimit: string = DEFAULT_STORAGE_LIMIT.REVEAL.toString()
): RevealOp {
return {
kind: 'reveal',
counter,
source,
fee,
gas_limit: gasLimit,
storage_limit: storageLimit,
public_key: pubKey,
};
}
/**
* Create an origination operation for the generic multisg contract. It does not create a reveal
* operation for the source account.
*
* @param {string} counter Valid source account counter to use
* @param {string} source Source account address
* @param {string} fee Fees in mutez to pay by the source account
* @param {string} gasLimit Maximum amount in mutez to spend in gas fees
* @param {string} storageLimit Maximum amount in mutez to spend in storage fees
* @param {string} balance New multisig account initial balance taken from the source account
* @param {string[]} pubKeys List of public keys of the multisig owner
* @param {string} delegate Optional implicit address to delegate the wallet funds to
* @param {number} threshold Minimum number of signatures required to authorize a multisig operation
* @returns An origination operation
*/
export function genericMultisigOriginationOperation(
counter: string,
source: string,
fee: string,
gasLimit: string,
storageLimit: string,
balance: string,
pubKeys: string[],
delegate?: string,
threshold: number = DEFAULT_N
): OriginationOp {
const walletPublicKeys: any[] = [];
pubKeys.forEach((pk) => walletPublicKeys.push({ string: pk }));
const originationOp: OriginationOp = {
kind: 'origination',
counter,
source,
fee,
gas_limit: gasLimit,
storage_limit: storageLimit,
balance,
script: {
code: genericMultisig,
storage: {
prim: 'Pair',
args: [
{
int: '0',
},
{
prim: 'Pair',
args: [
{
int: threshold.toString(),
},
walletPublicKeys,
],
},
],
},
},
};
if (delegate) {
originationOp.delegate = delegate;
}
return originationOp;
}
/**
* Get the public key of each owner of an multisig wallet origination contract.
*
* @param {OriginationOp} operation An operation with the generic multisig wallet origination
* @returns {string[]} List of all the owners set in the origination transaction
*/
export function getOwnersPublicKeys(operation: OriginationOp): string[] {
const ownersArgs = _.get(operation, 'script.storage.args[1].args[1]');
if (!ownersArgs) {
return [];
}
return ownersArgs.map((o) => o.string);
}
/**
* Generic Multisig contract from https://github.com/murbard/smart-contracts/blob/master/multisig/michelson/generic.tz
*/
const genericMultisig = [
{
prim: 'parameter',
args: [
{
prim: 'or',
args: [
{ prim: 'unit', annots: ['%default'] },
{
prim: 'pair',
args: [
{
prim: 'pair',
args: [
{
prim: 'nat',
annots: ['%counter'],
},
{
prim: 'or',
args: [
{
prim: 'lambda',
args: [
{ prim: 'unit' },
{
prim: 'list',
args: [
{
prim: 'operation',
},
],
},
],
annots: ['%operation'],
},
{
prim: 'pair',
args: [
{
prim: 'nat',
annots: ['%threshold'],
},
{
prim: 'list',
args: [{ prim: 'key' }],
annots: ['%keys'],
},
],
annots: ['%change_keys'],
},
],
annots: [':action'],
},
],
annots: [':payload'],
},
{
prim: 'list',
args: [
{
prim: 'option',
args: [{ prim: 'signature' }],
},
],
annots: ['%sigs'],
},
],
annots: ['%main'],
},
],
},
],
},
{
prim: 'storage',
args: [
{
prim: 'pair',
args: [
{
prim: 'nat',
annots: ['%stored_counter'],
},
{
prim: 'pair',
args: [
{
prim: 'nat',
annots: ['%threshold'],
},
{
prim: 'list',
args: [{ prim: 'key' }],
annots: ['%keys'],
},
],
},
],
},
],
},
{
prim: 'code',
args: [
[
[
[
{ prim: 'DUP' },
{ prim: 'CAR' },
{
prim: 'DIP',
args: [[{ prim: 'CDR' }]],
},
],
],
{
prim: 'IF_LEFT',
args: [
[
{ prim: 'DROP' },
{
prim: 'NIL',
args: [{ prim: 'operation' }],
},
{ prim: 'PAIR' },
],
[
{
prim: 'PUSH',
args: [{ prim: 'mutez' }, { int: '0' }],
},
{ prim: 'AMOUNT' },
[
[{ prim: 'COMPARE' }, { prim: 'EQ' }],
{
prim: 'IF',
args: [[], [[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]]],
},
],
{ prim: 'SWAP' },
{ prim: 'DUP' },
{
prim: 'DIP',
args: [[{ prim: 'SWAP' }]],
},
{
prim: 'DIP',
args: [
[
[
[
{ prim: 'DUP' },
{ prim: 'CAR' },
{
prim: 'DIP',
args: [[{ prim: 'CDR' }]],
},
],
],
{ prim: 'DUP' },
{ prim: 'SELF' },
{ prim: 'ADDRESS' },
{ prim: 'PAIR' },
{ prim: 'PACK' },
{
prim: 'DIP',
args: [
[
[
[
{ prim: 'DUP' },
{
prim: 'CAR',
annots: ['@counter'],
},
{
prim: 'DIP',
args: [
[
{
prim: 'CDR',
},
],
],
},
],
],
{
prim: 'DIP',
args: [[{ prim: 'SWAP' }]],
},
],
],
},
{ prim: 'SWAP' },
],
],
},
[
[
{ prim: 'DUP' },
{
prim: 'CAR',
annots: ['@stored_counter'],
},
{
prim: 'DIP',
args: [[{ prim: 'CDR' }]],
},
],
],
{
prim: 'DIP',
args: [[{ prim: 'SWAP' }]],
},
[
[{ prim: 'COMPARE' }, { prim: 'EQ' }],
{
prim: 'IF',
args: [[], [[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]]],
},
],
{
prim: 'DIP',
args: [[{ prim: 'SWAP' }]],
},
[
[
{ prim: 'DUP' },
{
prim: 'CAR',
annots: ['@threshold'],
},
{
prim: 'DIP',
args: [
[
{
prim: 'CDR',
annots: ['@keys'],
},
],
],
},
],
],
{
prim: 'DIP',
args: [
[
{
prim: 'PUSH',
args: [{ prim: 'nat' }, { int: '0' }],
annots: ['@valid'],
},
{ prim: 'SWAP' },
{
prim: 'ITER',
args: [
[
{
prim: 'DIP',
args: [[{ prim: 'SWAP' }]],
},
{ prim: 'SWAP' },
{
prim: 'IF_CONS',
args: [
[
[
{
prim: 'IF_NONE',
args: [
[
{
prim: 'SWAP',
},
{
prim: 'DROP',
},
],
[
{
prim: 'SWAP',
},
{
prim: 'DIP',
args: [
[
{
prim: 'SWAP',
},
{
prim: 'DIP',
args: [
{
int: '2',
},
[
[
{
prim: 'DIP',
args: [
[
{
prim: 'DUP',
},
],
],
},
{
prim: 'SWAP',
},
],
],
],
},
[
[
{
prim: 'DIP',
args: [
{
int: '2',
},
[
{
prim: 'DUP',
},
],
],
},
{
prim: 'DIG',
args: [
{
int: '3',
},
],
},
],
{
prim: 'DIP',
args: [
[
{
prim: 'CHECK_SIGNATURE',
},
],
],
},
{
prim: 'SWAP',
},
{
prim: 'IF',
args: [
[
{
prim: 'DROP',
},
],
[
{
prim: 'FAILWITH',
},
],
],
},
],
{
prim: 'PUSH',
args: [
{
prim: 'nat',
},
{
int: '1',
},
],
},
{
prim: 'ADD',
annots: ['@valid'],
},
],
],
},
],
],
},
],
],
[
[
{
prim: 'UNIT',
},
{
prim: 'FAILWITH',
},
],
],
],
},
{ prim: 'SWAP' },
],
],
},
],
],
},
[
[{ prim: 'COMPARE' }, { prim: 'LE' }],
{
prim: 'IF',
args: [[], [[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]]],
},
],
{
prim: 'IF_CONS',
args: [[[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]], []],
},
{ prim: 'DROP' },
{
prim: 'DIP',
args: [
[
[
[
{ prim: 'DUP' },
{ prim: 'CAR' },
{
prim: 'DIP',
args: [[{ prim: 'CDR' }]],
},
],
],
{
prim: 'PUSH',
args: [{ prim: 'nat' }, { int: '1' }],
},
{
prim: 'ADD',
annots: ['@new_counter'],
},
{ prim: 'PAIR' },
],
],
},
{
prim: 'IF_LEFT',
args: [
[{ prim: 'UNIT' }, { prim: 'EXEC' }],
[
{
prim: 'DIP',
args: [[{ prim: 'CAR' }]],
},
{ prim: 'SWAP' },
{ prim: 'PAIR' },
{
prim: 'NIL',
args: [{ prim: 'operation' }],
},
],
],
},
{ prim: 'PAIR' },
],
],
},
],
],
},
];
/**
* Add contract address to forwarder contract template and return contract Michelson code as JSON
*
* @param {string} contractAddress - multisig contractAddress that will receive forwarded funds
* @returns {object[]} Michelson code for the origination operation
*/
function createForwarder(contractAddress: string) {
return [
{
prim: 'parameter',
args: [
{
prim: 'or',
args: [
{ prim: 'unit', annots: ['%default'] },
{
prim: 'pair',
args: [
{ prim: 'nat' },
{
prim: 'contract',
args: [
{
prim: 'pair',
args: [
{ prim: 'address', annots: [':from'] },
{
prim: 'pair',
args: [
{ prim: 'address', annots: [':to'] },
{ prim: 'nat', annots: [':value'] },
],
},
],
},
],
},
],
annots: ['%flush'],
},
],
},
],
},
{ prim: 'storage', args: [{ prim: 'unit' }] },
{
prim: 'code',
args: [
[
{
prim: 'CAST',
args: [
{
prim: 'pair',
args: [
{
prim: 'or',
args: [
{ prim: 'unit' },
{
prim: 'pair',
args: [
{ prim: 'nat' },
{
prim: 'contract',
args: [
{
prim: 'pair',
args: [
{ prim: 'address' },
{ prim: 'pair', args: [{ prim: 'address' }, { prim: 'nat' }] },
],
},
],
},
],
},
],
},
{ prim: 'unit' },
],
},
],
},
{ prim: 'CAR' },
{
prim: 'IF_LEFT',
args: [
[
{ prim: 'DROP' },
{
prim: 'NONE',
args: [
{
prim: 'pair',
args: [
{ prim: 'nat' },
{
prim: 'contract',
args: [
{
prim: 'pair',
args: [
{ prim: 'address' },
{ prim: 'pair', args: [{ prim: 'address' }, { prim: 'nat' }] },
],
},
],
},
],
},
],
},
],
[{ prim: 'SOME' }],
],
},
{ prim: 'DIP', args: [[{ prim: 'PUSH', args: [{ prim: 'address' }, { string: contractAddress }] }]] },
{
prim: 'IF_NONE',
args: [
[{ prim: 'NIL', args: [{ prim: 'operation' }] }],
[
{ prim: 'DIP', args: [[{ prim: 'DUP' }]] },
{ prim: 'DUP' },
{ prim: 'CAR' },
{ prim: 'DIP', args: [[{ prim: 'CDR' }]] },
{ prim: 'DIG', args: [{ int: '2' }] },
{ prim: 'PAIR' },
{ prim: 'SELF' },
{ prim: 'ADDRESS' },
{ prim: 'PAIR' },
{ prim: 'DIP', args: [[{ prim: 'PUSH', args: [{ prim: 'mutez' }, { int: '0' }] }]] },
{ prim: 'TRANSFER_TOKENS' },
{ prim: 'DIP', args: [[{ prim: 'NIL', args: [{ prim: 'operation' }] }]] },
{ prim: 'CONS' },
],
],
},
{ prim: 'BALANCE' },
{ prim: 'PUSH', args: [{ prim: 'mutez' }, { int: '0' }] },
{ prim: 'COMPARE' },
{ prim: 'EQ' },
{
prim: 'IF',
args: [
[{ prim: 'DIP', args: [[{ prim: 'DROP' }]] }],
[
{
prim: 'DIP',
args: [
[
{ prim: 'CONTRACT', args: [{ prim: 'unit' }] },
{
prim: 'IF_NONE',
args: [
[
{ prim: 'PUSH', args: [{ prim: 'string' }, { string: 'not a wallet' }] },
{ prim: 'FAILWITH' },
],
[],
],
},
{ prim: 'BALANCE' },
{ prim: 'UNIT' },
{ prim: 'TRANSFER_TOKENS' },
],
],
},
{ prim: 'SWAP' },
{ prim: 'CONS' },
],
],
},
{ prim: 'DIP', args: [[{ prim: 'UNIT' }]] },
{ prim: 'PAIR' },
],
],
},
];
}
/**
* Create an origination operation for a forwarder contract
*
* @param {string} contractAddress originated multisig address to forward funds
* @param {string} counter Valid source account counter to use
* @param {string} source Source account address
* @param {string} fee Fees in mutez to pay by the source account
* @param {string} gasLimit Maximum amount in mutez to spend in gas fees
* @param {string} storageLimit Maximum amount in mutez to spend in storage fees
* @param {string} balance New multisig account initial balance taken from the source account
* @returns {OriginationOp} the operation
*/
export function forwarderOriginationOperation(
contractAddress: string,
counter: string,
source: string,
fee: string,
gasLimit: string,
storageLimit: string,
balance: string
): OriginationOp {
return {
kind: 'origination',
counter,
source,
fee,
gas_limit: gasLimit,
storage_limit: storageLimit,
balance,
script: {
code: createForwarder(contractAddress),
storage: { prim: 'Unit' },
},
};
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!