From c0f25675fc8606d5af7c3c88f71422350a9aa328 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 23:38:25 -0700 Subject: [PATCH 1/4] open vaults --- .../tezos/contracts/MurbardMultisigHelper.ts | 90 +++++++------- .../tezos/contracts/WrappedTezosHelper.ts | 113 ++++++++++++++++-- 2 files changed, 147 insertions(+), 56 deletions(-) diff --git a/src/chain/tezos/contracts/MurbardMultisigHelper.ts b/src/chain/tezos/contracts/MurbardMultisigHelper.ts index e99e5723..38578083 100644 --- a/src/chain/tezos/contracts/MurbardMultisigHelper.ts +++ b/src/chain/tezos/contracts/MurbardMultisigHelper.ts @@ -8,55 +8,55 @@ import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; export namespace MurbardMultisigHelper { - /** - * Gets the contract code at the specified address at the head block and compares it to the known hash of the code. This function processes Micheline format contracts. - * - * @param server Destination Tezos node. - * @param address Contract address to query. - */ - export async function verifyDestination(server: string, address: string): Promise { - const contract = await TezosNodeReader.getAccountForBlock(server, 'head', address); + /** + * Gets the contract code at the specified address at the head block and compares it to the known hash of the code. This function processes Micheline format contracts. + * + * @param server Destination Tezos node. + * @param address Contract address to query. + */ + export async function verifyDestination(server: string, address: string): Promise { + const contract = await TezosNodeReader.getAccountForBlock(server, 'head', address); - if (!!!contract.script) { throw new Error(`No code found at ${address}`); } + if (!!!contract.script) { throw new Error(`No code found at ${address}`); } - const k = Buffer.from(blakejs.blake2s(JSON.stringify(contract.script.code), null, 16)).toString('hex'); + const k = Buffer.from(blakejs.blake2s(JSON.stringify(contract.script.code), null, 16)).toString('hex'); - if (k !== '914629850cfdad7b54a8c5a661d10bd0') { throw new Error(`Contract does not match the expected code hash: ${k}, '914629850cfdad7b54a8c5a661d10bd0'`); } + if (k !== '914629850cfdad7b54a8c5a661d10bd0') { throw new Error(`Contract does not match the expected code hash: ${k}, '914629850cfdad7b54a8c5a661d10bd0'`); } - return true; - } + return true; + } - /** - * In contrast to verifyDestination, this function uses compares Michelson hashes. - * - * @param script - */ - export function verifyScript(script: string): boolean { - const k = Buffer.from(blakejs.blake2s(TezosLanguageUtil.preProcessMichelsonScript(script).join('\n'), null, 16)).toString('hex'); + /** + * In contrast to verifyDestination, this function uses compares Michelson hashes. + * + * @param script + */ + export function verifyScript(script: string): boolean { + const k = Buffer.from(blakejs.blake2s(TezosLanguageUtil.preProcessMichelsonScript(script).join('\n'), null, 16)).toString('hex'); - if (k !== 'ffcad1e376a6c8915780fe6676aceec6') { throw new Error(`Contract does not match the expected code hash: ${k}, 'ffcad1e376a6c8915780fe6676aceec6'`); } + if (k !== 'ffcad1e376a6c8915780fe6676aceec6') { throw new Error(`Contract does not match the expected code hash: ${k}, 'ffcad1e376a6c8915780fe6676aceec6'`); } - return true; - } + return true; + } - export async function getSimpleStorage(server: string, address: string): Promise<{ counter: number, threshold: number, keys: string[] }> { - const storageResult = await TezosNodeReader.getContractStorage(server, address); + export async function getSimpleStorage(server: string, address: string): Promise<{ counter: number, threshold: number, keys: string[] }> { + const storageResult = await TezosNodeReader.getContractStorage(server, address); - return { - counter: Number(JSONPath({ path: '$.args[0].int', json: storageResult })[0]), - threshold: Number(JSONPath({ path: '$.args[1].args[0].int', json: storageResult })[0]), - keys: JSONPath({ path: '$.args[1].args[1]..string', json: storageResult }) - }; - } + return { + counter: Number(JSONPath({ path: '$.args[0].int', json: storageResult })[0]), + threshold: Number(JSONPath({ path: '$.args[1].args[0].int', json: storageResult })[0]), + keys: JSONPath({ path: '$.args[1].args[1]..string', json: storageResult }) + }; + } - /** - * Sample multi-sig contract retrieved in April 2020. - * https://github.com/murbard/smart-contracts/blob/master/multisig/michelson/multisig.tzip - */ - export async function deployContract(server: string, signer: Signer, keyStore: KeyStore, delegate: string, fee: number, amount: number, counter: number, threshold: number, keys: string[]): Promise { - if (threshold > keys.length) { throw new Error('Number of keys provided is lower than the threshold'); } + /** + * Sample multi-sig contract retrieved in April 2020. + * https://github.com/murbard/smart-contracts/blob/master/multisig/michelson/multisig.tzip + */ + export async function deployContract(server: string, signer: Signer, keyStore: KeyStore, delegate: string, fee: number, amount: number, counter: number, threshold: number, keys: string[]): Promise { + if (threshold > keys.length) { throw new Error('Number of keys provided is lower than the threshold'); } - const code = `parameter (pair (pair :payload (nat %counter) (or :action (pair :transfer (mutez %amount) (contract %dest unit)) (or (option %delegate key_hash) (pair %change_keys (nat %threshold) (list %keys key))))) (list %sigs (option signature))); + const code = `parameter (pair (pair :payload (nat %counter) (or :action (pair :transfer (mutez %amount) (contract %dest unit)) (or (option %delegate key_hash) (pair %change_keys (nat %threshold) (list %keys key))))) (list %sigs (option signature))); storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys key))); code { @@ -106,13 +106,13 @@ export namespace MurbardMultisigHelper { { DIP { SWAP ; CAR } ; SWAP ; PAIR ; SWAP }} ; PAIR }`; - const storage = `(Pair ${counter} (Pair ${threshold} { "${keys.join('" ; "') }" } ) )`; + const storage = `(Pair ${counter} (Pair ${threshold} { "${keys.join('" ; "')}" } ) )`; - const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(server, signer, keyStore, amount, delegate, fee, 5_000, 120_000, code, storage, TezosTypes.TezosParameterFormat.Michelson); - return clearRPCOperationGroupHash(nodeResult['operationGroupID']); - } + const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(server, signer, keyStore, amount, delegate, fee, 5_000, 120_000, code, storage, TezosTypes.TezosParameterFormat.Michelson); + return clearRPCOperationGroupHash(nodeResult['operationGroupID']); + } - function clearRPCOperationGroupHash(hash: string): string { - return hash.replace(/\"/g, '').replace(/\n/, ''); - } + function clearRPCOperationGroupHash(hash: string): string { + return hash.replace(/\"/g, '').replace(/\n/, ''); + } } diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 17854b9c..4fe88bb5 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -1,4 +1,6 @@ import { JSONPath } from 'jsonpath-plus'; +import base58Check from "bs58check"; +import * as blakejs from 'blakejs'; import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; @@ -6,13 +8,13 @@ import { TezosMessageUtils } from '../TezosMessageUtil'; import { TezosNodeReader } from '../TezosNodeReader'; import { TezosNodeWriter } from '../TezosNodeWriter'; import { TezosContractUtils } from './TezosContractUtils'; +import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { token: 'd48b45bd77d2300026fe617c5ba7670e', - oven: '5e3c30607da21a0fc30f7be61afb15c7' - - // TODO(keefertaylor): Implement additional checksums for core contract here. + oven: '5e3c30607da21a0fc30f7be61afb15c7', + core: '7b9b5b7e7f0283ff6388eb783e23c452' } /** The expected checksum for the Wrapped Tezos scripts. */ @@ -21,8 +23,19 @@ const SCRIPT_CHECKSUMS = { token: '', // TODO(keefertaylor): Compute this checksum correctly. oven: '', + // TODO(keefertaylor): Compute this checksum correctly. + core: '' +} + +/** + * Property bag containing the results of opening an oven. + */ +export type OpenOvenResult = { + // The operation hash of the request to open an oven. + operationHash: string - // TODO(keefertaylor): Implement additional checksums for core script here. + // The address of the new oven contract. + ovenAddress: string } /** @@ -51,18 +64,20 @@ export namespace WrappedTezosHelper { * @param nodeUrl The URL of the Tezos node which serves data. * @param tokenContractAddress The address of the token contract. * @param ovenContractAddress The address of an oven contract. + * @param coreContractAddress The address of the core contract. * @returns A boolean indicating if the code was the expected sum. */ export async function verifyDestination( nodeUrl: string, tokenContractAddress: string, - ovenContractAddress: string + ovenContractAddress: string, + coreContractAddress: string ): Promise { - // TODO(keefertaylor): Verify checksums for core contract here. const tokenMatched = TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token) const ovenMatched = TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven) + const coreMatched = TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core) - return tokenMatched && ovenMatched + return tokenMatched && ovenMatched && coreMatched } /** @@ -72,15 +87,16 @@ export namespace WrappedTezosHelper { * * @param tokenScript The script of the token contract. * @param ovenScript The script of an oven contract. + * @param coreScript The script of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - export function verifyScript(tokenScript: string): boolean { - // TODO(keefertaylor): Verify checksums for core script here. + export function verifyScript(tokenScript: string, ovenScript, string, coreScript: string): boolean { const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) - const ovenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.oven) + const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven) + const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core) - return tokenMatched && ovenMatched + return tokenMatched && ovenMatched && coreMatched } /** @@ -237,4 +253,79 @@ export namespace WrappedTezosHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + + export async function openOven( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + fee: number, + coreAddress: string, + gasLimit: number, + storageLimit: number + ): Promise { + const entryPoint = 'runEntrypointLambda' + const lambdaName = 'createOven' + const bytes = TezosMessageUtils.writePackedData(`Pair None "${keystore.publicKeyHash}"`, 'pair (option key_hash) address', TezosParameterFormat.Michelson) + const parameters = `Pair "${lambdaName}" 0x${bytes}` + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + coreAddress, + 0, + fee, + storageLimit, + gasLimit, + entryPoint, + parameters, + TezosTypes.TezosParameterFormat.Michelson + ) + + const operationHash = TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + const ovenAddress = calculateContractAddress(operationHash, 0) + return { + operationHash, + ovenAddress + } + } + + /** + * Calculate the address of a contract that was originated. + * + * TODO(anonymoussprocket): This funcition is probably useful elsewhere in ConseilJS. Consider refactoring. + * + * @param operationHash The operation group hash. + * @param index The index of the origination operation in the operation group. + */ + function calculateContractAddress(operationHash: string, index: number): string { + // Decode and slice two byte prefix off operation hash. + const decoded: Uint8Array = base58Check.decode(operationHash).slice(2) + + // Merge the decoded buffer with the operation prefix. + let decodedAndOperationPrefix: Array = [] + for (let i = 0; i < decoded.length; i++) { + decodedAndOperationPrefix.push(decoded[i]) + } + decodedAndOperationPrefix = decodedAndOperationPrefix.concat([ + (index & 0xff000000) >> 24, + (index & 0x00ff0000) >> 16, + (index & 0x0000ff00) >> 8, + index & 0x000000ff, + ]) + + // Hash and encode. + const hash = blakejs.blake2b(new Uint8Array(decodedAndOperationPrefix), null, 20) + const smartContractAddressPrefix = new Uint8Array([2, 90, 121]) // KT1 + const prefixedBytes = mergeBytes(smartContractAddressPrefix, hash) + return base58Check.encode(prefixedBytes) + } + + function mergeBytes(a: Uint8Array, b: Uint8Array): Uint8Array { + const merged = new Uint8Array(a.length + b.length) + merged.set(a) + merged.set(b, a.length) + + return merged + } } From 204d2a2b801c8f2a2c79044bef24abf06f9262f6 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 23:43:32 -0700 Subject: [PATCH 2/4] revert mubarb --- .../tezos/contracts/MurbardMultisigHelper.ts | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/chain/tezos/contracts/MurbardMultisigHelper.ts b/src/chain/tezos/contracts/MurbardMultisigHelper.ts index 38578083..e99e5723 100644 --- a/src/chain/tezos/contracts/MurbardMultisigHelper.ts +++ b/src/chain/tezos/contracts/MurbardMultisigHelper.ts @@ -8,55 +8,55 @@ import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; export namespace MurbardMultisigHelper { - /** - * Gets the contract code at the specified address at the head block and compares it to the known hash of the code. This function processes Micheline format contracts. - * - * @param server Destination Tezos node. - * @param address Contract address to query. - */ - export async function verifyDestination(server: string, address: string): Promise { - const contract = await TezosNodeReader.getAccountForBlock(server, 'head', address); + /** + * Gets the contract code at the specified address at the head block and compares it to the known hash of the code. This function processes Micheline format contracts. + * + * @param server Destination Tezos node. + * @param address Contract address to query. + */ + export async function verifyDestination(server: string, address: string): Promise { + const contract = await TezosNodeReader.getAccountForBlock(server, 'head', address); - if (!!!contract.script) { throw new Error(`No code found at ${address}`); } + if (!!!contract.script) { throw new Error(`No code found at ${address}`); } - const k = Buffer.from(blakejs.blake2s(JSON.stringify(contract.script.code), null, 16)).toString('hex'); + const k = Buffer.from(blakejs.blake2s(JSON.stringify(contract.script.code), null, 16)).toString('hex'); - if (k !== '914629850cfdad7b54a8c5a661d10bd0') { throw new Error(`Contract does not match the expected code hash: ${k}, '914629850cfdad7b54a8c5a661d10bd0'`); } + if (k !== '914629850cfdad7b54a8c5a661d10bd0') { throw new Error(`Contract does not match the expected code hash: ${k}, '914629850cfdad7b54a8c5a661d10bd0'`); } - return true; - } + return true; + } - /** - * In contrast to verifyDestination, this function uses compares Michelson hashes. - * - * @param script - */ - export function verifyScript(script: string): boolean { - const k = Buffer.from(blakejs.blake2s(TezosLanguageUtil.preProcessMichelsonScript(script).join('\n'), null, 16)).toString('hex'); + /** + * In contrast to verifyDestination, this function uses compares Michelson hashes. + * + * @param script + */ + export function verifyScript(script: string): boolean { + const k = Buffer.from(blakejs.blake2s(TezosLanguageUtil.preProcessMichelsonScript(script).join('\n'), null, 16)).toString('hex'); - if (k !== 'ffcad1e376a6c8915780fe6676aceec6') { throw new Error(`Contract does not match the expected code hash: ${k}, 'ffcad1e376a6c8915780fe6676aceec6'`); } + if (k !== 'ffcad1e376a6c8915780fe6676aceec6') { throw new Error(`Contract does not match the expected code hash: ${k}, 'ffcad1e376a6c8915780fe6676aceec6'`); } - return true; - } + return true; + } - export async function getSimpleStorage(server: string, address: string): Promise<{ counter: number, threshold: number, keys: string[] }> { - const storageResult = await TezosNodeReader.getContractStorage(server, address); + export async function getSimpleStorage(server: string, address: string): Promise<{ counter: number, threshold: number, keys: string[] }> { + const storageResult = await TezosNodeReader.getContractStorage(server, address); - return { - counter: Number(JSONPath({ path: '$.args[0].int', json: storageResult })[0]), - threshold: Number(JSONPath({ path: '$.args[1].args[0].int', json: storageResult })[0]), - keys: JSONPath({ path: '$.args[1].args[1]..string', json: storageResult }) - }; - } + return { + counter: Number(JSONPath({ path: '$.args[0].int', json: storageResult })[0]), + threshold: Number(JSONPath({ path: '$.args[1].args[0].int', json: storageResult })[0]), + keys: JSONPath({ path: '$.args[1].args[1]..string', json: storageResult }) + }; + } - /** - * Sample multi-sig contract retrieved in April 2020. - * https://github.com/murbard/smart-contracts/blob/master/multisig/michelson/multisig.tzip - */ - export async function deployContract(server: string, signer: Signer, keyStore: KeyStore, delegate: string, fee: number, amount: number, counter: number, threshold: number, keys: string[]): Promise { - if (threshold > keys.length) { throw new Error('Number of keys provided is lower than the threshold'); } + /** + * Sample multi-sig contract retrieved in April 2020. + * https://github.com/murbard/smart-contracts/blob/master/multisig/michelson/multisig.tzip + */ + export async function deployContract(server: string, signer: Signer, keyStore: KeyStore, delegate: string, fee: number, amount: number, counter: number, threshold: number, keys: string[]): Promise { + if (threshold > keys.length) { throw new Error('Number of keys provided is lower than the threshold'); } - const code = `parameter (pair (pair :payload (nat %counter) (or :action (pair :transfer (mutez %amount) (contract %dest unit)) (or (option %delegate key_hash) (pair %change_keys (nat %threshold) (list %keys key))))) (list %sigs (option signature))); + const code = `parameter (pair (pair :payload (nat %counter) (or :action (pair :transfer (mutez %amount) (contract %dest unit)) (or (option %delegate key_hash) (pair %change_keys (nat %threshold) (list %keys key))))) (list %sigs (option signature))); storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys key))); code { @@ -106,13 +106,13 @@ export namespace MurbardMultisigHelper { { DIP { SWAP ; CAR } ; SWAP ; PAIR ; SWAP }} ; PAIR }`; - const storage = `(Pair ${counter} (Pair ${threshold} { "${keys.join('" ; "')}" } ) )`; + const storage = `(Pair ${counter} (Pair ${threshold} { "${keys.join('" ; "') }" } ) )`; - const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(server, signer, keyStore, amount, delegate, fee, 5_000, 120_000, code, storage, TezosTypes.TezosParameterFormat.Michelson); - return clearRPCOperationGroupHash(nodeResult['operationGroupID']); - } + const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(server, signer, keyStore, amount, delegate, fee, 5_000, 120_000, code, storage, TezosTypes.TezosParameterFormat.Michelson); + return clearRPCOperationGroupHash(nodeResult['operationGroupID']); + } - function clearRPCOperationGroupHash(hash: string): string { - return hash.replace(/\"/g, '').replace(/\n/, ''); - } + function clearRPCOperationGroupHash(hash: string): string { + return hash.replace(/\"/g, '').replace(/\n/, ''); + } } From 2979f64404b668ec80e2ba21fd8e09578b6f2931 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 09:40:33 -0700 Subject: [PATCH 3/4] refactor to helper --- src/chain/tezos/TezosMessageUtil.ts | 44 +++++++++++++++++++ .../tezos/contracts/WrappedTezosHelper.ts | 43 +----------------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/chain/tezos/TezosMessageUtil.ts b/src/chain/tezos/TezosMessageUtil.ts index 3acbcc74..6ac3d10a 100644 --- a/src/chain/tezos/TezosMessageUtil.ts +++ b/src/chain/tezos/TezosMessageUtil.ts @@ -552,4 +552,48 @@ export namespace TezosMessageUtils { return n.toJSNumber(); } + + /** + * Calculate the address of a contract that was originated. + * + * @param operationHash The operation group hash. + * @param index The index of the origination operation in the operation group. + */ + export function calculateContractAddress(operationHash: string, index: number): string { + // Decode and slice two byte prefix off operation hash. + const decoded: Uint8Array = base58check.decode(operationHash).slice(2) + + // Merge the decoded buffer with the operation prefix. + let decodedAndOperationPrefix: Array = [] + for (let i = 0; i < decoded.length; i++) { + decodedAndOperationPrefix.push(decoded[i]) + } + decodedAndOperationPrefix = decodedAndOperationPrefix.concat([ + (index & 0xff000000) >> 24, + (index & 0x00ff0000) >> 16, + (index & 0x0000ff00) >> 8, + index & 0x000000ff, + ]) + + // Hash and encode. + const hash = blakejs.blake2b(new Uint8Array(decodedAndOperationPrefix), null, 20) + const smartContractAddressPrefix = new Uint8Array([2, 90, 121]) // KT1 + const prefixedBytes = mergeBytes(smartContractAddressPrefix, hash) + return base58check.encode(prefixedBytes) + } + + /** + * Helper to merge two Uint8Arrays. + * + * @param a The first array. + * @param b The second array. + * @returns A new array that contains b appended to the end of a. + */ + function mergeBytes(a: Uint8Array, b: Uint8Array): Uint8Array { + const merged = new Uint8Array(a.length + b.length) + merged.set(a) + merged.set(b, a.length) + + return merged + } } diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 50f86274..a2e1fa46 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -1,6 +1,4 @@ import { JSONPath } from 'jsonpath-plus'; -import base58Check from "bs58check"; -import * as blakejs from 'blakejs'; import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; @@ -321,49 +319,10 @@ export namespace WrappedTezosHelper { ) const operationHash = TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - const ovenAddress = calculateContractAddress(operationHash, 0) + const ovenAddress = TezosMessageUtils.calculateContractAddress(operationHash, 0) return { operationHash, ovenAddress } } - - /** - * Calculate the address of a contract that was originated. - * - * TODO(anonymoussprocket): This funcition is probably useful elsewhere in ConseilJS. Consider refactoring. - * - * @param operationHash The operation group hash. - * @param index The index of the origination operation in the operation group. - */ - function calculateContractAddress(operationHash: string, index: number): string { - // Decode and slice two byte prefix off operation hash. - const decoded: Uint8Array = base58Check.decode(operationHash).slice(2) - - // Merge the decoded buffer with the operation prefix. - let decodedAndOperationPrefix: Array = [] - for (let i = 0; i < decoded.length; i++) { - decodedAndOperationPrefix.push(decoded[i]) - } - decodedAndOperationPrefix = decodedAndOperationPrefix.concat([ - (index & 0xff000000) >> 24, - (index & 0x00ff0000) >> 16, - (index & 0x0000ff00) >> 8, - index & 0x000000ff, - ]) - - // Hash and encode. - const hash = blakejs.blake2b(new Uint8Array(decodedAndOperationPrefix), null, 20) - const smartContractAddressPrefix = new Uint8Array([2, 90, 121]) // KT1 - const prefixedBytes = mergeBytes(smartContractAddressPrefix, hash) - return base58Check.encode(prefixedBytes) - } - - function mergeBytes(a: Uint8Array, b: Uint8Array): Uint8Array { - const merged = new Uint8Array(a.length + b.length) - merged.set(a) - merged.set(b, a.length) - - return merged - } } From 3bedc1552e9567322de80bd8dd92412b748ac1b8 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 09:44:26 -0700 Subject: [PATCH 4/4] add docs --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index a2e1fa46..fa73dabe 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -290,6 +290,20 @@ export namespace WrappedTezosHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + /** + * Open a new oven. + * + * The oven's owner is assigned to the sender's address. + * + * @param nodeUrl The URL of the Tezos node which serves data. + * @param signer A Signer for the sourceAddress. + * @param keystore A Keystore for the sourceAddress. + * @param fee The fee to use. + * @param coreAddress The address of the core contract. + * @param gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @returns A property bag of data about the operation. + */ export async function openOven( nodeUrl: string, signer: Signer,