|
import * as fs from 'fs'; |
|
import * as glob from 'glob'; |
|
|
|
import { TezosConseilClient, TezosWalletUtil, TezosNodeWriter, BabylonDelegationHelper, setLogLevel, TezosParameterFormat, KeyStore, OperationKindType, TezosNodeReader, TezosContractIntrospector } from 'conseiljs'; |
|
|
|
setLogLevel('debug'); |
|
|
|
const tezosNode = '<tezos-node-url>'; |
|
const conseilServer = { url: '<conseil-indexer-url>', apiKey: '<APIKEY_from_nautuilus.cloud>', network: 'carthagenet' }; |
|
const networkBlockTime = 30 + 1; |
|
|
|
let faucetAccount = {}; |
|
let keystore: KeyStore; |
|
let contractAddress: string; |
|
let delegationContractAddress: string; |
|
const bakerAddress = 'tz1VxS7ff4YnZRs8b4mMP4WaMVpoQjuo1rjf'; |
|
const anotherBakerAddress = 'tz3gN8NTLNLJg5KRsUU47NHNVHbdhcFXjjaB'; |
|
const accountAddress = 'tz1iwTKp5NEdDJSjNVLcYtB7AdELQvoS5tfS'; |
|
const anotherAccountAddress = 'tz1QmzkDPazvKYtLMS5Sxbz41vxBmykmk2TU'; |
|
|
|
function clearRPCOperationGroupHash(hash: string) { |
|
return hash.replace(/\"/g, '').replace(/\n/, ''); |
|
} |
|
|
|
async function initAccount(): Promise<KeyStore> { |
|
console.log('~~ initAccount'); |
|
let faucetFiles: string[] = glob.sync('tz1*.json'); |
|
|
|
if (faucetFiles.length === 0) { |
|
throw new Error('Did not find any faucet files, please go to faucet.tzalpha.net to get one'); |
|
} |
|
|
|
console.log(`loading ${faucetFiles[0]} faucet file`); |
|
faucetAccount = JSON.parse(fs.readFileSync(faucetFiles[0], 'utf8')); |
|
|
|
const keystore = await TezosWalletUtil.unlockFundraiserIdentity(faucetAccount['mnemonic'].join(' '), faucetAccount['email'], faucetAccount['password'], faucetAccount['pkh']); |
|
console.log(`public key: ${keystore.publicKey}`); |
|
console.log(`secret key: ${keystore.privateKey}`); |
|
console.log(`account hash: ${keystore.publicKeyHash}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
|
|
return keystore; |
|
} |
|
|
|
async function activateAccount(): Promise<string> { |
|
console.log(`~~ activateAccount`); |
|
const accountRecord = await TezosConseilClient.getAccount(conseilServer, conseilServer.network, keystore.publicKeyHash); |
|
if (accountRecord !== undefined) { return accountRecord['account_id']; } |
|
|
|
const nodeResult = await TezosNodeWriter.sendIdentityActivationOperation(tezosNode, keystore, faucetAccount['secret']); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected activation operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Activated account at ${conseilResult.pkh}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
return conseilResult.pkh; |
|
} |
|
|
|
async function revealAccount(): Promise<string> { |
|
console.log(`~~ revealAccount`); |
|
if (await TezosNodeReader.isManagerKeyRevealedForAccount(tezosNode, keystore.publicKeyHash)) { |
|
return keystore.publicKeyHash; |
|
} |
|
|
|
const nodeResult = await TezosNodeWriter.sendKeyRevealOperation(tezosNode, keystore); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected reveal operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Revealed account at ${conseilResult.source}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
return conseilResult.source; |
|
} |
|
|
|
async function sendTransaction() { |
|
console.log(`~~ sendTransaction: 500000µtz from ${keystore.publicKeyHash} into ${accountAddress}`); |
|
const nodeResult = await TezosNodeWriter.sendTransactionOperation(tezosNode, keystore, accountAddress, 500000, 1500, ''); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected transaction operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Completed transfer of ${conseilResult.amount}µtz`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
} |
|
|
|
async function delegatePrimaryAccount() { |
|
console.log(`~~ delegatePrimaryAccount`); |
|
const nodeResult = await BabylonDelegationHelper.setDelegate(tezosNode, keystore, keystore.publicKeyHash, bakerAddress, 20000); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected delegation operation with ${groupid}`); |
|
|
|
await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
} |
|
|
|
async function deployDelegationContract(): Promise<string> { |
|
console.log(`~~ deployDelegationContract: from ${keystore.publicKeyHash} to ${anotherBakerAddress} with 500000µtz`); |
|
const nodeResult = await BabylonDelegationHelper.deployManagerContract(tezosNode, keystore, anotherBakerAddress, 20000, 500000); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected origination operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Originated contract at ${conseilResult.originated_contracts}, delegated to ${conseilResult.delegate}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
return conseilResult.originated_contracts; |
|
} |
|
|
|
async function depositDelegatedFunds() { |
|
console.log(`~~ depositDelegatedFunds: 5 xtz from ${keystore.publicKeyHash} into ${delegationContractAddress}`); |
|
const nodeResult = await BabylonDelegationHelper.depositDelegatedFunds(tezosNode, keystore, delegationContractAddress, 20000, 5000000); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected an operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Completed transfer of ${conseilResult.amount}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
} |
|
|
|
async function sendDelegatedFunds() { |
|
console.log(`~~ sendDelegatedFunds: 500000µtz from ${delegationContractAddress} into ${anotherAccountAddress}`); |
|
const nodeResult = await BabylonDelegationHelper.sendDelegatedFunds(tezosNode, keystore, delegationContractAddress, 20000, 500000, undefined, anotherAccountAddress); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected an operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Completed transfer of ${conseilResult.amount}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
} |
|
|
|
async function delegationContractWithdraw() { |
|
console.log(`~~ delegationContractWithdraw: 500000µtz from ${delegationContractAddress} into ${keystore.publicKeyHash}`); |
|
const nodeResult = await BabylonDelegationHelper.withdrawDelegatedFunds(tezosNode, keystore, delegationContractAddress, 20000, 500000); |
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected an operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Completed transfer of ${conseilResult.amount}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
} |
|
|
|
async function deployMichelineContract(): Promise<string> { |
|
console.log(`~~ deployMichelineContract`); |
|
const contract = `[ |
|
{ "prim":"parameter", "args":[ { "prim":"string" } ] }, |
|
{ "prim":"storage", "args":[ { "prim":"string" } ] }, |
|
{ |
|
"prim":"code", |
|
"args":[ |
|
[ |
|
{ "prim":"CAR" }, |
|
{ "prim":"NIL", "args":[ { "prim":"operation" } ] }, |
|
{ "prim":"PAIR" } |
|
] |
|
] |
|
} |
|
]`; |
|
const storage = '{"string": "Sample"}'; |
|
|
|
const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosNode, keystore, 0, undefined, 100000, '', 1000, 100000, contract, storage, TezosParameterFormat.Micheline); |
|
const groupid = clearRPCOperationGroupHash(nodeResult['operationGroupID']); |
|
console.log(`Injected origination operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Originated contract at ${conseilResult.originated_contracts}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
return conseilResult.originated_contracts; |
|
} |
|
|
|
async function deployMichelsonContract(): Promise<string> { |
|
console.log(`~~ deployMichelsonContract`); |
|
const contract = `parameter string; |
|
storage string; |
|
code { DUP; |
|
DIP { CDR ; NIL string ; SWAP ; CONS } ; |
|
CAR ; CONS ; |
|
CONCAT; |
|
NIL operation; PAIR}`; |
|
const storage = '"Sample"'; |
|
|
|
const fee = Number((await TezosConseilClient.getFeeStatistics(conseilServer, conseilServer.network, OperationKindType.Origination))[0]['high']); |
|
|
|
const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosNode, keystore, 0, undefined, fee, '', 1000, 100000, contract, storage, TezosParameterFormat.Michelson); |
|
const groupid = clearRPCOperationGroupHash(nodeResult['operationGroupID']); |
|
console.log(`Injected origination operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Originated contract at ${conseilResult.originated_contracts}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
return conseilResult.originated_contracts; |
|
} |
|
|
|
async function invokeContract(address: string, parameter: string, entrypoint: string = '') { |
|
console.log(`~~ invokeContract`); |
|
const fee = Number((await TezosConseilClient.getFeeStatistics(conseilServer, conseilServer.network, OperationKindType.Transaction))[0]['high']); |
|
|
|
let storageResult = await TezosNodeReader.getContractStorage(tezosNode, address); |
|
console.log(`initial storage: ${JSON.stringify(storageResult)}`); |
|
|
|
const { gas, storageCost: freight } = await TezosNodeWriter.testContractInvocationOperation(tezosNode, 'main', keystore, address, 10000, fee, 1000, 100000, entrypoint, parameter, TezosParameterFormat.Michelson); |
|
|
|
console.log(`cost: ${JSON.stringify(await TezosNodeWriter.testContractInvocationOperation(tezosNode, 'main', keystore, address, 10000, fee, 1000, 100000, entrypoint, parameter, TezosParameterFormat.Michelson))}`) |
|
const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosNode, keystore, address, 10000, fee, '', freight, gas, entrypoint, parameter, TezosParameterFormat.Michelson); |
|
|
|
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID); |
|
console.log(`Injected transaction(invocation) operation with ${groupid}`); |
|
|
|
const conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime); |
|
console.log(`Completed invocation of ${conseilResult.destination}`); |
|
storageResult = await TezosNodeReader.getContractStorage(tezosNode, address); |
|
console.log(`modified storage: ${JSON.stringify(storageResult)}`); |
|
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); |
|
} |
|
|
|
async function parseContract(address: string) { |
|
const entryPoints = await TezosContractIntrospector.generateEntryPointsFromAddress(conseilServer, conseilServer.network, address); |
|
for (const entryPoint of entryPoints) { |
|
console.log(`${entryPoint.name}(${entryPoint.parameters.map(p => (p.name ? p.name + ': ' : '') + p.type + (p.optional ? '?' : '')).join(', ')})`) |
|
console.log(entryPoint.structure) |
|
} |
|
} |
|
|
|
async function dumpMempool(account: string) { |
|
const rr = await TezosNodeReader.getMempoolOperationsForAccount(tezosNode, account); |
|
|
|
await Promise.all( |
|
rr.map(async (r) => { |
|
const ttl = await TezosNodeReader.estimateBranchTimeout(tezosNode, r['branch']); |
|
const t = r['contents'][0]; |
|
console.log(`operation ${r['hash']} for ${new BigNumber(t.amount || 0).toNumber()}xtz expires in ${ttl} blocks`) |
|
}) |
|
); |
|
} |
|
|
|
async function run() { |
|
// Account initialization |
|
keystore = await initAccount(); // TODO: read/write settings |
|
await activateAccount(); |
|
await revealAccount(); |
|
|
|
// Basic operations |
|
await sendTransaction(); |
|
await delegatePrimaryAccount(); |
|
|
|
// Delegation operations |
|
delegationContractAddress = await deployDelegationContract(); |
|
await depositDelegatedFunds(); |
|
await sendDelegatedFunds(); |
|
await delegationContractWithdraw(); |
|
|
|
// Basic contract operations |
|
await deployMichelineContract(); |
|
contractAddress = await deployMichelsonContract(); |
|
await invokeContract(contractAddress, '"new text"'); |
|
} |
|
|
|
run(); |
This comment has been minimized.
If you're getting error 404 not found, then try changing your Tezos Bablylonnet Node address from
https://tezos-dev.cryptonomic-infra.tech/
tohttps://conseil-dev.cryptonomic-infra.tech:443
in index.ts