From 7bb318d023459ba604ec7b2203a45976ba6793d5 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Wed, 30 Sep 2020 00:36:43 -0400 Subject: [PATCH 01/60] - dump encoded messages to debug log --- src/chain/tezos/TezosNodeWriter.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/chain/tezos/TezosNodeWriter.ts b/src/chain/tezos/TezosNodeWriter.ts index 872681e1..17751441 100644 --- a/src/chain/tezos/TezosNodeWriter.ts +++ b/src/chain/tezos/TezosNodeWriter.ts @@ -50,11 +50,10 @@ export namespace TezosNodeWriter { */ // TODO: move to an appropriate place export function forgeOperations(branch: string, operations: TezosP2PMessageTypes.Operation[]): string { - log.debug('TezosNodeWriter.forgeOperations:'); - log.debug(JSON.stringify(operations)); + log.debug(`TezosNodeWriter.forgeOperations: ${JSON.stringify(operations)}`); let encoded = TezosMessageUtils.writeBranch(branch); operations.forEach(m => encoded += TezosMessageCodec.encodeOperation(m)); - + log.debug(`TezosNodeWriter.forgeOperations: ${encoded}`); return encoded; } From 232ba95fc14ea6321a4ed1029160944bb7b51f57 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Tue, 20 Oct 2020 21:19:01 -0400 Subject: [PATCH 02/60] - initial dexter pool conract support --- src/chain/tezos/contracts/DexterPoolHelper.ts | 205 ++++++++++++++++++ .../tezos/contracts/DexterTokenHelper.ts | 75 ------- src/index-web.ts | 2 +- src/index.ts | 2 +- 4 files changed, 207 insertions(+), 77 deletions(-) create mode 100644 src/chain/tezos/contracts/DexterPoolHelper.ts delete mode 100644 src/chain/tezos/contracts/DexterTokenHelper.ts diff --git a/src/chain/tezos/contracts/DexterPoolHelper.ts b/src/chain/tezos/contracts/DexterPoolHelper.ts new file mode 100644 index 00000000..d878f1c8 --- /dev/null +++ b/src/chain/tezos/contracts/DexterPoolHelper.ts @@ -0,0 +1,205 @@ +import bigInt from 'big-integer'; +import { JSONPath } from 'jsonpath-plus'; + +import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; +import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; +import { TezosNodeReader } from '../TezosNodeReader'; +import { TezosNodeWriter } from '../TezosNodeWriter'; +import { TezosContractUtils } from './TezosContractUtils'; +import { TezosMessageUtils } from '../TezosMessageUtil'; + +interface DexterPoolSimpleStorage { + balanceMap: number; + administrator: string; + token: string; + tokenBalance: number; + xtzBalance: number; + selfIsUpdatingTokenPool: boolean; + freeze_baker: boolean; + lqt_total: number; +} + +/** + * mainnet KT1DrJV8vhkdLEj76h1H9Q4irZDqAkMPo1Qf tzbtc + * mainner KT1Puc9St8wdNoGtLiD2WXaHbWU7styaxYhD usdtz + * + * https://gitlab.com/camlcase-dev/dexter-integration + */ +export namespace DexterPoolHelper { + const DexterPoolLiquidityOperationGasLimit = 500_000; + const DexterPoolLiquidityOperationStorageLimit = 5_000; + const DexterPoolExchangeOperationGasLimit = 500_000; + const DexterPoolExchangeOperationStorageLimit = 5_000; + const ExchangeMultiplier = 997; + + /** + * 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 { + return TezosContractUtils.verifyDestination(server, address, 'a72954311c48dcc28279590d82870611'); + } + + /** + * In contrast to verifyDestination, this function uses compares Michelson hashes. + * + * @param script + */ + export function verifyScript(script: string): boolean { + return TezosContractUtils.verifyScript(script, 'yyy'); + } + + export async function getSimpleStorage(server: string, address: string): Promise { + const storageResult = await TezosNodeReader.getContractStorage(server, address); + + return { + balanceMap: Number(JSONPath({ path: '$.args[0].int', json: storageResult })[0]), + administrator: JSONPath({ path: '$.args[1].args[1].args[0].args[0].string', json: storageResult })[0], + token: JSONPath({ path: '$.args[1].args[1].args[0].args[1].string', json: storageResult })[0], + tokenBalance: Number(JSONPath({ path: '$.args[1].args[1].args[1].args[1].int', json: storageResult })[0]), + xtzBalance: Number(JSONPath({ path: '$.args[1].args[1].args[1].args[0].int', json: storageResult })[0]), + selfIsUpdatingTokenPool: (JSONPath({ path: '$.args[1].args[0].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), + freeze_baker: (JSONPath({ path: '$.args[1].args[0].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), + lqt_total: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[1].int', json: storageResult })[0]) + }; + } + + export async function getAccountBalance(server: string, mapid: number, account: string): Promise { + try { + const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); + const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); + + if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${account}`); } + + const jsonresult = JSONPath({ path: '$.args[0].int', json: mapResult }); + return Number(jsonresult[0]); + } catch { + return 0; + } + } + + export async function getAccountAllowance(server: string, mapid: number, account: string, spender: string) { + const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); + const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); + + if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${account}/${spender}`); } + + let allowances = new Map(); + JSONPath({ path: '$.args[1][*].args', json: mapResult }).forEach(v => allowances[v[0]['string']] = Number(v[1]['int'])); + + return allowances[spender] || 0; + } + + export async function addLiquidity(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, xtzAmount: number, liquidityAmount: number, tokenAmount: number, expiration: Date): Promise { + //(pair (address :owner) (nat :minLqtMinted)) (pair (nat :maxTokensDeposited) (timestamp :deadline))) + const parameters = `(Pair (Pair "${keyStore.publicKeyHash}" ${liquidityAmount}) (Pair ${tokenAmount} "${expiration.toISOString()}"))`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(server, signer, keyStore, contract, xtzAmount, fee, DexterPoolLiquidityOperationStorageLimit, DexterPoolLiquidityOperationGasLimit, 'addLiquidity', parameters, TezosTypes.TezosParameterFormat.Michelson); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + export async function removeLiquidity(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, balance: number, xtzBalance: number, tokenBalance: number, expiration: Date): Promise { + //(pair (address :owner) (pair (address :to) (nat :lqtBurned))) (pair (mutez :minXtzWithdrawn) (pair (nat :minTokensWithdrawn) (timestamp :deadline))) + const parameters = `(Pair (Pair "${keyStore.publicKeyHash}" (Pair "${keyStore.publicKeyHash}" ${balance})) (Pair ${xtzBalance} (Pair ${tokenBalance} "${expiration.toISOString()}")))`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(server, signer, keyStore, contract, 0, fee, DexterPoolLiquidityOperationStorageLimit, DexterPoolLiquidityOperationGasLimit, 'removeLiquidity', parameters, TezosTypes.TezosParameterFormat.Michelson); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + export async function xtzToToken(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, xtzAmount: number, tokenAmount: number, expiration: Date): Promise { + //(pair %xtzToToken (address :to) (pair (nat :minTokensBought) (timestamp :deadline))) + const parameters = `(Pair "${keyStore.publicKeyHash}" (Pair ${tokenAmount} "${expiration.toISOString()}"))`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(server, signer, keyStore, contract, xtzAmount, fee, DexterPoolExchangeOperationStorageLimit, DexterPoolExchangeOperationGasLimit, 'xtzToToken', parameters, TezosTypes.TezosParameterFormat.Michelson); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + export async function tokenToXtz(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, xtzAmount: number, tokenAmount: number, expiration: Date): Promise { + //(pair %tokenToXtz (pair (address :owner) (address :to)) (pair (nat :tokensSold) (pair (mutez :minXtzBought) (timestamp :deadline)))) + const parameters = `(Pair (Pair "${keyStore.publicKeyHash}" "${keyStore.publicKeyHash}") (Pair ${tokenAmount} (Pair ${xtzAmount} "${expiration.toISOString()}")))`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(server, signer, keyStore, contract, 0, fee, DexterPoolExchangeOperationStorageLimit, DexterPoolExchangeOperationGasLimit, 'tokenToXtz', parameters, TezosTypes.TezosParameterFormat.Michelson); + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + export async function tokenToToken(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, otherPoolContract: string, sellAmount: number, buyAmount: number, expiration: Date): Promise { + //(pair %tokenToToken (pair (address :outputDexterContract) (pair (nat :minTokensBought) (address :owner))) (pair (address :to) (pair (nat :tokensSold) (timestamp :deadline)))) + const parameters = `(Pair (Pair "${otherPoolContract}" (Pair ${buyAmount} "${keyStore.publicKeyHash}")) (Pair "${keyStore.publicKeyHash}" (Pair ${sellAmount} "${expiration.toISOString()}")))`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(server, signer, keyStore, contract, 0, fee, DexterPoolExchangeOperationStorageLimit, 1_000_000, 'tokenToToken', parameters, TezosTypes.TezosParameterFormat.Michelson); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + export async function approve(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, spender: string, newAllowance: number, currentAllowance: number): Promise { + //(pair %approve (address :spender) (pair (nat :allowance) (nat :currentAllowance))) + const parameters = `(Pair "${spender}" (Pair ${newAllowance} ${currentAllowance}))`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(server, signer, keyStore, contract, 0, fee, DexterPoolExchangeOperationStorageLimit, DexterPoolExchangeOperationGasLimit, 'approve', parameters, TezosTypes.TezosParameterFormat.Michelson); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + /** + * Show pending applied operations against this contract in the mempool + */ + export async function previewTransactions() { + // + } + + /** + * + * @param xtzDeposit XTZ amount of the proposed transaction + * @param tokenBalance Pool token balance + * @param xtzBalance Pool XTZ balance + * @returns Token amount required for the matching XTZ balance + */ + export function calcTokenLiquidityRequirement(xtzDeposit: number, tokenBalance: number, xtzBalance: number): number { + return bigInt(xtzDeposit).multiply(bigInt(tokenBalance)).divide(bigInt(xtzBalance)).toJSNumber(); + } + + /** + * Returns the token exchange rate for a given XTZ amount. + * + * @param xtzDeposit + * @param tokenBalance + * @param xtzBalance + */ + export function getTokenExchangeRate(xtzAmount: number, tokenBalance: number, xtzBalance: number) { + const n = bigInt(xtzAmount).multiply(bigInt(tokenBalance)).multiply(bigInt(ExchangeMultiplier)); + const d = bigInt(xtzBalance).multiply(bigInt(1000)).add(bigInt(xtzAmount).multiply(bigInt(ExchangeMultiplier))) + + return n.divide(d).divide(bigInt(xtzAmount)).toJSNumber(); + } + + /** + * Returns the XTZ exchange rate for a given token amount + * + * @param tokenAmount + * @param tokenBalance + * @param xtzBalance + */ + export function getXTZExchangeRate(tokenAmount: number, tokenBalance: number, xtzBalance: number) { + const n = bigInt(tokenAmount).multiply(bigInt(xtzBalance)).multiply(bigInt(ExchangeMultiplier)); + const d = bigInt(tokenBalance).multiply(bigInt(1000)).add(bigInt(tokenAmount).multiply(bigInt(ExchangeMultiplier))) + + return n.divide(d).divide(bigInt(tokenAmount)).toJSNumber(); + } + + //const lqtMinted = bigInt(xtzDeposit).multiply(bigInt(poolStorage.lqt_total)).divide(bigInt(poolStorage.xtzBalance)).toJSNumber(); + + /** + * Estimates the cost of buying 1% share of the pool in terms of XTZ + */ + export function estimateShareCost(xtzBalance: number, tokenBalance: number): { xtzCost: number, tokenCost: number } { + const xtzShare = bigInt(xtzBalance).divide(bigInt(100)).toJSNumber(); + const tokenShare = calcTokenLiquidityRequirement(xtzShare, tokenBalance, xtzBalance); + + return { xtzCost: xtzShare, tokenCost: tokenShare }; + } +} diff --git a/src/chain/tezos/contracts/DexterTokenHelper.ts b/src/chain/tezos/contracts/DexterTokenHelper.ts deleted file mode 100644 index 7cc05c1f..00000000 --- a/src/chain/tezos/contracts/DexterTokenHelper.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as blakejs from 'blakejs'; -import { JSONPath } from 'jsonpath-plus'; - -import { TezosMessageUtils } from '../TezosMessageUtil'; -import { TezosNodeReader } from '../TezosNodeReader'; - -/** - * Awaiting contracts at https://gitlab.com/camlcase-dev/dexter - */ -export namespace DexterTokenHelper { - /** - * Gets the contract code at the specified address at the head block and compares it to the known hash of the code. - * - * @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}`); } - - const k = Buffer.from(blakejs.blake2s(contract['script'].toString(), null, 16)).toString('hex'); - - if (k !== '1234') { throw new Error(`Contract at ${address} does not match the expected code hash`); } - - return true; - } - - /** - * Retrieves high level storage, including map id and token supply cap. - * - * @param server Destination Tezos node. - * @param address Contract address to query. - */ - export async function getBasicStorage(server: string, address: string) { - const storageResult = await TezosNodeReader.getContractStorage(server, address); - console.log('-----') - console.log(storageResult); - console.log('-----') - - return { - mapid: Number(JSONPath({ path: '$.args[0].int', json: storageResult })[0]), - totalSupply: Number(JSONPath({ path: '$.args[1].int', json: storageResult })[0]) - }; - } - - /** - * - * - * @param server Destination Tezos node. - * @param mapid bigmap reference to query. - * @param account Account address to query. - */ - export async function getAddressRecord(server: string, mapid: number, account: string) { - const key = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); - const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, key); - - if (!!!mapResult) { return undefined; } - - return { - allowances: JSONPath({ path: '$.args[0]', json: mapResult })[0], - balance: Number(JSONPath({ path: '$.args[1].int', json: mapResult })[0]) - }; - } - - /** - * - * @param server Destination Tezos node. - * @param manager Token manager address - * @param supply Initial token supply - */ - export async function deployContract(server: string, manager: string, supply: number) { - - } -} diff --git a/src/index-web.ts b/src/index-web.ts index f370935c..2d867cab 100644 --- a/src/index-web.ts +++ b/src/index-web.ts @@ -11,7 +11,7 @@ export * from './chain/tezos/TezosNodeReader'; export * from './chain/tezos/TezosNodeWriter'; export * from './chain/tezos/contracts/BabylonDelegationHelper'; export * from './chain/tezos/contracts/CryptonomicNameServiceHelper'; -export * from './chain/tezos/contracts/DexterTokenHelper'; +export * from './chain/tezos/contracts/DexterPoolHelper'; export * from './chain/tezos/contracts/MurbardMultisigHelper'; export * from './chain/tezos/contracts/StakerDAOTokenHelper'; export * from './chain/tezos/contracts/TCFBakerRegistryHelper'; diff --git a/src/index.ts b/src/index.ts index 2fd2c535..486b98cb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,7 +16,7 @@ export * from "./chain/tezos/TezosNodeReader"; export * from "./chain/tezos/TezosNodeWriter"; export * from './chain/tezos/contracts/BabylonDelegationHelper'; export * from './chain/tezos/contracts/CryptonomicNameServiceHelper'; -export * from './chain/tezos/contracts/DexterTokenHelper'; +export * from './chain/tezos/contracts/DexterPoolHelper'; export * from './chain/tezos/contracts/MurbardMultisigHelper'; export * from './chain/tezos/contracts/StakerDAOTokenHelper'; export * from './chain/tezos/contracts/TCFBakerRegistryHelper'; From 23b5f830ba8784c24bdb4da9716d7d0b9294f6b5 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Tue, 20 Oct 2020 22:30:40 -0400 Subject: [PATCH 03/60] - bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2bd31875..d6d085f1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "conseiljs", - "version": "5.0.5", + "version": "5.0.6", "description": "Client-side library for Tezos dApp development.", "browser": "dist/index-web.js", "main": "dist/index.js", From bcc858b93773bd2f3486b232c529a61acfbc4b15 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Mon, 9 Nov 2020 01:56:35 -0500 Subject: [PATCH 04/60] - Dexter unit tests --- src/chain/tezos/contracts/DexterPoolHelper.ts | 169 +++++++++++++++--- .../tezos/contracts/DexterPoolHelper.spec.ts | 69 +++++++ 2 files changed, 216 insertions(+), 22 deletions(-) create mode 100644 test/chain/tezos/contracts/DexterPoolHelper.spec.ts diff --git a/src/chain/tezos/contracts/DexterPoolHelper.ts b/src/chain/tezos/contracts/DexterPoolHelper.ts index d878f1c8..4152710f 100644 --- a/src/chain/tezos/contracts/DexterPoolHelper.ts +++ b/src/chain/tezos/contracts/DexterPoolHelper.ts @@ -20,10 +20,11 @@ interface DexterPoolSimpleStorage { } /** - * mainnet KT1DrJV8vhkdLEj76h1H9Q4irZDqAkMPo1Qf tzbtc - * mainner KT1Puc9St8wdNoGtLiD2WXaHbWU7styaxYhD usdtz + * Contract wrapper for http://dexter.exchange/ pool contracts, intended for use on mainnet with KT1Puc9St8wdNoGtLiD2WXaHbWU7styaxYhD (usdtz) and KT1DrJV8vhkdLEj76h1H9Q4irZDqAkMPo1Qf (tzbtc). + * + * Tested on carthagenet with KT1RtNatBzmk2AvJKm9Mx6b55GcQejJneK7t. * - * https://gitlab.com/camlcase-dev/dexter-integration + * Based on integration documentation provided at https://gitlab.com/camlcase-dev/dexter-integration. */ export namespace DexterPoolHelper { const DexterPoolLiquidityOperationGasLimit = 500_000; @@ -51,6 +52,21 @@ export namespace DexterPoolHelper { return TezosContractUtils.verifyScript(script, 'yyy'); } + /** + * Queries the tezos node directly for basic contract storage. + * + * @param server Destination Tezos node. + * @param address Contract address to query. + * @returns + * - balanceMap: bigmap index of the liquidity balance map + * - administrator: Contract administrator + * - token: Token address this pool services + * - tokenBalance: Total token balance held in the pool + * - xtzBalance: Total XTZ balance held in the pool + * - selfIsUpdatingTokenPool + * - freeze_baker + * - lqt_total Liquidity token balance + */ export async function getSimpleStorage(server: string, address: string): Promise { const storageResult = await TezosNodeReader.getContractStorage(server, address); @@ -66,6 +82,13 @@ export namespace DexterPoolHelper { }; } + /** + * Queries the Tezos node for the liquidity balance of the requested account. + * + * @param server Destination Tezos node. + * @param mapid bigmap id of the pool to query. + * @param account Account to query. + */ export async function getAccountBalance(server: string, mapid: number, account: string): Promise { try { const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); @@ -80,6 +103,14 @@ export namespace DexterPoolHelper { } } + /** + * Queries the Tezos node for the liquidity balance approval for a given spender on the requested account. + * + * @param server Destination Tezos node. + * @param mapid bigmap id of the pool to query. + * @param account Account to query. + * @param spender Spender to get balance for. + */ export async function getAccountAllowance(server: string, mapid: number, account: string, spender: string) { const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); @@ -92,7 +123,20 @@ export namespace DexterPoolHelper { return allowances[spender] || 0; } - export async function addLiquidity(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, xtzAmount: number, liquidityAmount: number, tokenAmount: number, expiration: Date): Promise { + /** + * Adds liquidity to the pool using the `addLiquidity` entry point of the contract pool. Deposits both XTZ and a matching token balance. + * + * @param server Destination Tezos node. + * @param signer + * @param keyStore + * @param contract + * @param fee + * @param liquidityAmount Expected liquidity amount + * @param xtzAmount + * @param tokenAmount + * @param expiration Request expiration date. + */ + export async function addLiquidity(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, liquidityAmount: number, xtzAmount: number, tokenAmount: number, expiration: Date): Promise { //(pair (address :owner) (nat :minLqtMinted)) (pair (nat :maxTokensDeposited) (timestamp :deadline))) const parameters = `(Pair (Pair "${keyStore.publicKeyHash}" ${liquidityAmount}) (Pair ${tokenAmount} "${expiration.toISOString()}"))`; @@ -101,6 +145,19 @@ export namespace DexterPoolHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + /** + * Removes liquidity from the pool using the `removeLiquidity` entry point. + * + * @param server Destination Tezos node. + * @param signer + * @param keyStore + * @param contract + * @param fee + * @param balance Liquidity amount to withdraw. + * @param xtzBalance Expected XTZ balance + * @param tokenBalance Expected token balance + * @param expiration Request expiration date. + */ export async function removeLiquidity(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, balance: number, xtzBalance: number, tokenBalance: number, expiration: Date): Promise { //(pair (address :owner) (pair (address :to) (nat :lqtBurned))) (pair (mutez :minXtzWithdrawn) (pair (nat :minTokensWithdrawn) (timestamp :deadline))) const parameters = `(Pair (Pair "${keyStore.publicKeyHash}" (Pair "${keyStore.publicKeyHash}" ${balance})) (Pair ${xtzBalance} (Pair ${tokenBalance} "${expiration.toISOString()}")))`; @@ -110,6 +167,18 @@ export namespace DexterPoolHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + /** + * + * Convert an XTZz balance into an token balance. + * @param server + * @param signer + * @param keyStore + * @param contract + * @param fee + * @param xtzAmount + * @param tokenAmount + * @param expiration Request expiration date. + */ export async function xtzToToken(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, xtzAmount: number, tokenAmount: number, expiration: Date): Promise { //(pair %xtzToToken (address :to) (pair (nat :minTokensBought) (timestamp :deadline))) const parameters = `(Pair "${keyStore.publicKeyHash}" (Pair ${tokenAmount} "${expiration.toISOString()}"))`; @@ -119,6 +188,18 @@ export namespace DexterPoolHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + /** + * Convert a token balance into an XTZ balance. + * + * @param server Destination Tezos node. + * @param signer + * @param keyStore + * @param contract + * @param fee + * @param xtzAmount + * @param tokenAmount + * @param expiration Request expiration date. + */ export async function tokenToXtz(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, xtzAmount: number, tokenAmount: number, expiration: Date): Promise { //(pair %tokenToXtz (pair (address :owner) (address :to)) (pair (nat :tokensSold) (pair (mutez :minXtzBought) (timestamp :deadline)))) const parameters = `(Pair (Pair "${keyStore.publicKeyHash}" "${keyStore.publicKeyHash}") (Pair ${tokenAmount} (Pair ${xtzAmount} "${expiration.toISOString()}")))`; @@ -127,6 +208,19 @@ export namespace DexterPoolHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + /** + * Untested function that should allow exchange of a token for a different token instead of xtz. + * + * @param server Destination Tezos node. + * @param signer + * @param keyStore + * @param contract + * @param fee + * @param otherPoolContract + * @param sellAmount + * @param buyAmount + * @param expiration Request expiration date. + */ export async function tokenToToken(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, otherPoolContract: string, sellAmount: number, buyAmount: number, expiration: Date): Promise { //(pair %tokenToToken (pair (address :outputDexterContract) (pair (nat :minTokensBought) (address :owner))) (pair (address :to) (pair (nat :tokensSold) (timestamp :deadline)))) const parameters = `(Pair (Pair "${otherPoolContract}" (Pair ${buyAmount} "${keyStore.publicKeyHash}")) (Pair "${keyStore.publicKeyHash}" (Pair ${sellAmount} "${expiration.toISOString()}")))`; @@ -136,6 +230,18 @@ export namespace DexterPoolHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + /** + * Approves a spender for a share of the liquidity balance on the given account. + * + * @param server Destination Tezos node. + * @param signer + * @param keyStore + * @param contract + * @param fee + * @param spender + * @param newAllowance + * @param currentAllowance + */ export async function approve(server: string, signer: Signer, keyStore: KeyStore, contract: string, fee: number, spender: string, newAllowance: number, currentAllowance: number): Promise { //(pair %approve (address :spender) (pair (nat :allowance) (nat :currentAllowance))) const parameters = `(Pair "${spender}" (Pair ${newAllowance} ${currentAllowance}))`; @@ -149,57 +255,76 @@ export namespace DexterPoolHelper { * Show pending applied operations against this contract in the mempool */ export async function previewTransactions() { - // + // TODO } /** + * Calculate the token requirement for the proposed XTZ deposit. * * @param xtzDeposit XTZ amount of the proposed transaction * @param tokenBalance Pool token balance * @param xtzBalance Pool XTZ balance - * @returns Token amount required for the matching XTZ balance + * @return {number} Matching token balance for the proposed deposit */ export function calcTokenLiquidityRequirement(xtzDeposit: number, tokenBalance: number, xtzBalance: number): number { return bigInt(xtzDeposit).multiply(bigInt(tokenBalance)).divide(bigInt(xtzBalance)).toJSNumber(); } /** - * Returns the token exchange rate for a given XTZ amount. + * XTZ/Token exchange rate for a given XTZ trade. * - * @param xtzDeposit - * @param tokenBalance - * @param xtzBalance + * @param xtzAmount Proposed XTZ deposit + * @param tokenBalance Current token balance in the pool + * @param xtzBalance Current XTZ balance in the pool */ - export function getTokenExchangeRate(xtzAmount: number, tokenBalance: number, xtzBalance: number) { + export function getTokenExchangeRate(xtzAmount: number, tokenBalance: number, xtzBalance: number, xtzDecimals: number = 6) { const n = bigInt(xtzAmount).multiply(bigInt(tokenBalance)).multiply(bigInt(ExchangeMultiplier)); - const d = bigInt(xtzBalance).multiply(bigInt(1000)).add(bigInt(xtzAmount).multiply(bigInt(ExchangeMultiplier))) + const d = bigInt(xtzBalance).multiply(bigInt(1000)).add(bigInt(xtzAmount).multiply(bigInt(ExchangeMultiplier))); + + const tokenAmount = n.divide(d); + const dm = tokenAmount.divmod(bigInt(xtzAmount)); + const f = dm.remainder.multiply(bigInt(10 ** xtzDecimals)).divide(bigInt(xtzAmount)); - return n.divide(d).divide(bigInt(xtzAmount)).toJSNumber(); + return { tokenAmount: tokenAmount.toJSNumber(), rate: parseFloat(`${dm.quotient.toJSNumber()}.${f.toJSNumber()}`) }; } /** - * Returns the XTZ exchange rate for a given token amount + * Token/XTZ exchange rate for a given token trade. * - * @param tokenAmount - * @param tokenBalance - * @param xtzBalance + * @param tokenAmount Proposed token deposit + * @param tokenBalance Current token balance in the pool + * @param xtzBalance Current XTZ balance in the pool */ - export function getXTZExchangeRate(tokenAmount: number, tokenBalance: number, xtzBalance: number) { + export function getXTZExchangeRate(tokenAmount: number, tokenBalance: number, xtzBalance: number, tokenDecimals: number = 6) { const n = bigInt(tokenAmount).multiply(bigInt(xtzBalance)).multiply(bigInt(ExchangeMultiplier)); const d = bigInt(tokenBalance).multiply(bigInt(1000)).add(bigInt(tokenAmount).multiply(bigInt(ExchangeMultiplier))) - return n.divide(d).divide(bigInt(tokenAmount)).toJSNumber(); + const xtzAmount = n.divide(d); + const dm = xtzAmount.divmod(bigInt(tokenAmount)); + const f = dm.remainder.multiply(bigInt(10 ** tokenDecimals)).divide(bigInt(tokenAmount)); + + return { xtzAmount: xtzAmount.toJSNumber(), rate: parseFloat(`${dm.quotient.toJSNumber()}.${f.toJSNumber()}`) }; } - //const lqtMinted = bigInt(xtzDeposit).multiply(bigInt(poolStorage.lqt_total)).divide(bigInt(poolStorage.xtzBalance)).toJSNumber(); + /** + * Returns the amount of liquidity tokens a particular XTZ deposit would receive. + * @param xtzDeposit + * @param liquidityBalance + * @param xtzBalance + */ + export function estimateLiquidityAmount(xtzDeposit: number, liquidityBalance: number, xtzBalance: number) { + return bigInt(xtzDeposit).multiply(bigInt(liquidityBalance)).divide(bigInt(xtzBalance)).toJSNumber(); + } /** * Estimates the cost of buying 1% share of the pool in terms of XTZ */ - export function estimateShareCost(xtzBalance: number, tokenBalance: number): { xtzCost: number, tokenCost: number } { - const xtzShare = bigInt(xtzBalance).divide(bigInt(100)).toJSNumber(); + export function estimateShareCost(xtzBalance: number, tokenBalance: number, liquidityBalance: number): { xtzCost: number, tokenCost: number } { + const xtzShare = bigInt(xtzBalance).divide(bigInt(99)).toJSNumber(); const tokenShare = calcTokenLiquidityRequirement(xtzShare, tokenBalance, xtzBalance); + // TODO: use estimateLiquidityAmount + return { xtzCost: xtzShare, tokenCost: tokenShare }; } } diff --git a/test/chain/tezos/contracts/DexterPoolHelper.spec.ts b/test/chain/tezos/contracts/DexterPoolHelper.spec.ts new file mode 100644 index 00000000..332bf176 --- /dev/null +++ b/test/chain/tezos/contracts/DexterPoolHelper.spec.ts @@ -0,0 +1,69 @@ +import { expect } from 'chai'; +import { DexterPoolHelper } from '../../../../src/chain/tezos/contracts/DexterPoolHelper'; + +describe('DexterPoolHelper test suite', () => { + it('calcTokenLiquidityRequirement tests', () => { + // TODO + //let result = DexterPoolHelper.calcTokenLiquidityRequirement(xtzDeposit: number, tokenBalance: number, xtzBalance: number) + }); + + /** + * Test samples retrieved from https://gitlab.com/camlcase-dev/dexter-integration/-/raw/master/xtz_to_token.json on 2020/Oct/21. + */ + it('getTokenExchangeRate tests', () => { + const camlCaseSamples = [ + { "xtz_pool": "1000000000", "token_pool": "250000", "xtz_in": "1000000", "token_out": "249", "slippage": "0.0040" }, + { "xtz_pool": "1000000000", "token_pool": "250000", "xtz_in": "2000000", "token_out": "497", "slippage": "0.0059" }, + { "xtz_pool": "1000000000", "token_pool": "250000", "xtz_in": "5000000", "token_out": "1240", "slippage": "0.0079" }, + { "xtz_pool": "1000000000", "token_pool": "250000", "xtz_in": "10000000", "token_out": "2467", "slippage": "0.0132" }, + { "xtz_pool": "1000000000", "token_pool": "250000", "xtz_in": "100000000", "token_out": "22665", "slippage": "0.0934" }, + { "xtz_pool": "355200000", "token_pool": "30000", "xtz_in": "1000000", "token_out": "83", "slippage": "0.0172" }, + { "xtz_pool": "355200000", "token_pool": "30000", "xtz_in": "34020000", "token_out": "2614", "slippage": "0.0902" }, + { "xtz_pool": "10000000000", "token_pool": "15200", "xtz_in": "10000000", "token_out": "15", "slippage": "0.0131" }, + { "xtz_pool": "10000000000", "token_pool": "15200", "xtz_in": "23100000", "token_out": "34", "slippage": "0.0316" }, + { "xtz_pool": "10000000000", "token_pool": "15200", "xtz_in": "67000000", "token_out": "100", "slippage": "0.01806" }, + { "xtz_pool": "10000000000", "token_pool": "15200", "xtz_in": "1050000", "token_out": "1", "slippage": "0.3734" }, + { "xtz_pool": "10000000000", "token_pool": "15200", "xtz_in": "4423000", "token_out": "6", "slippage": "0.1075" }, + { "xtz_pool": "103000000", "token_pool": "101000", "xtz_in": "1000000", "token_out": "968", "slippage": "0.0128" }, + { "xtz_pool": "10000000", "token_pool": "1000", "xtz_in": "2000000", "token_out": "166", "slippage": "0.1700" }, + { "xtz_pool": "12000000", "token_pool": "834", "xtz_in": "2500000", "token_out": "143", "slippage": "0.1769" }, + { "xtz_pool": "14500000", "token_pool": "691", "xtz_in": "6125000", "token_out": "204", "slippage": "0.3011" }, + { "xtz_pool": "14500000", "token_pool": "1234", "xtz_in": "5000000", "token_out": "315", "slippage": "0.2597" } ]; + + for (const sample of camlCaseSamples) { + const result = DexterPoolHelper.getTokenExchangeRate(Number(sample.xtz_in), Number(sample.token_pool), Number(sample.xtz_pool)); + + expect(result.tokenAmount).to.equal(Number(sample.token_out)); + } + }); + + /** + * * Test samples retrieved from https://gitlab.com/camlcase-dev/dexter-integration/-/raw/master/token_to_xtz.json on 2020/Oct/21. + */ + it('getXTZExchangeRate tests', () => { + const camlCaseSamples = [ + { "xtz_pool": "20000000", "token_pool": "1000", "token_in": "1000", "xtz_out": "9984977", "slippage": "0.5007" }, + { "xtz_pool": "20000000", "token_pool": "1000", "token_in": "100", "xtz_out": "1813221", "slippage": "0.0933" }, + { "xtz_pool": "20000000", "token_pool": "1000", "token_in": "10", "xtz_out": "197431", "slippage": "0.0128" }, + { "xtz_pool": "20000000", "token_pool": "1000", "token_in": "1", "xtz_out": "19920", "slippage": "0.0040" }, + { "xtz_pool": "20000000", "token_pool": "1000", "token_in": "240", "xtz_out": "3861597", "slippage": "0.1955" }, + { "xtz_pool": "20000000", "token_pool": "1000", "token_in": "116", "xtz_out": "2073262", "slippage": "0.1063" }, + { "xtz_pool": "20000000", "token_pool": "1000", "token_in": "923", "xtz_out": "9584586", "slippage": "0.4807" }, + { "xtz_pool": "19500000", "token_pool": "919", "token_in": "100", "xtz_out": "1908461", "slippage": "0.1005" }, + { "xtz_pool": "17591539", "token_pool": "1019", "token_in": "81", "xtz_out": "1291776", "slippage": "0.0762" } ]; + + for (const sample of camlCaseSamples) { + const result = DexterPoolHelper.getXTZExchangeRate(Number(sample.token_in), Number(sample.token_pool), Number(sample.xtz_pool)); + + expect(result.xtzAmount).to.equal(Number(sample.xtz_out)); + } + }); + + it('estimateLiquidityAmount tests', () => { + //estimateLiquidityAmount(xtzDeposit: number, liquidityBalance: number, xtzBalance: number) + }); + + it('estimateShareCost tests', () => { + //estimateShareCost(xtzBalance: number, tokenBalance: number): { xtzCost: number, tokenCost: number } + }); +}); From 3dd4828f34339c163b62d70230c8f7b3adbda9ca Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Tue, 10 Nov 2020 01:23:58 -0500 Subject: [PATCH 05/60] - impoved awaitOperationConfirmation failure conditions --- src/reporting/ConseilDataClient.ts | 1 + src/reporting/tezos/TezosConseilClient.ts | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/reporting/ConseilDataClient.ts b/src/reporting/ConseilDataClient.ts index 278f1c03..755a017c 100644 --- a/src/reporting/ConseilDataClient.ts +++ b/src/reporting/ConseilDataClient.ts @@ -26,6 +26,7 @@ export namespace ConseilDataClient { return fetch(url, { method: 'post', headers: { 'apiKey': serverInfo.apiKey, 'Content-Type': 'application/json' }, + cache: 'no-store', body: JSON.stringify(query) }) .then(r => { diff --git a/src/reporting/tezos/TezosConseilClient.ts b/src/reporting/tezos/TezosConseilClient.ts index f1829ae9..6a963595 100644 --- a/src/reporting/tezos/TezosConseilClient.ts +++ b/src/reporting/tezos/TezosConseilClient.ts @@ -1,8 +1,12 @@ -import { ConseilQueryBuilder } from "../ConseilQueryBuilder"; import { ConseilQuery, ConseilOperator, ConseilServerInfo, ConseilSortDirection } from "../../types/conseil/QueryTypes" -import { ConseilDataClient } from "../ConseilDataClient"; import { OperationKindType } from "../../types/tezos/TezosChainTypes"; import { ContractMapDetails, ContractMapDetailsItem } from '../../types/conseil/ConseilTezosTypes'; +import LogSelector from '../../utils/LoggerSelector'; + +import { ConseilDataClient } from "../ConseilDataClient"; +import { ConseilQueryBuilder } from "../ConseilQueryBuilder"; + +const log = LogSelector.log; /** * Functions for querying the Conseil backend REST API v2 for Tezos chain data. @@ -207,18 +211,29 @@ export namespace TezosConseilClient { */ export async function awaitOperationConfirmation(serverInfo: ConseilServerInfo, network: string, hash: string, duration: number, blocktime: number = 60): Promise { if (duration <= 0) { throw new Error('Invalid duration'); } + const initialLevel = (await getBlockHead(serverInfo, network))['level']; + const timeOffset = 180000; + const startTime = (new Date).getTime() - timeOffset; + const estimatedEndTime = startTime + timeOffset + duration * blocktime * 1000; + + log.debug(`TezosConseilClient.awaitOperationConfirmation looking for ${hash} since ${initialLevel} at ${(new Date(startTime).toUTCString())}, +${duration}`); + let currentLevel = initialLevel; let operationQuery = ConseilQueryBuilder.blankQuery(); operationQuery = ConseilQueryBuilder.addPredicate(operationQuery , 'operation_group_hash', ConseilOperator.EQ, [hash], false); - operationQuery = ConseilQueryBuilder.addPredicate(operationQuery , 'timestamp', ConseilOperator.AFTER, [(new Date).getTime() - 60000], false); + operationQuery = ConseilQueryBuilder.addPredicate(operationQuery , 'timestamp', ConseilOperator.AFTER, [startTime], false); operationQuery = ConseilQueryBuilder.setLimit(operationQuery, 1); while (initialLevel + duration > currentLevel) { const group = await getOperations(serverInfo, network, operationQuery); if (group.length > 0) { return group[0]; } + currentLevel = (await getBlockHead(serverInfo, network))['level']; + if (initialLevel + duration < currentLevel) { break; } + if ((new Date).getTime() > estimatedEndTime) { break; } + await new Promise(resolve => setTimeout(resolve, blocktime * 1000)); } From 7b38c5a35a830d58037dd72d0fcaa7df4698c372 Mon Sep 17 00:00:00 2001 From: othmane el kesri Date: Wed, 18 Nov 2020 13:08:02 +0100 Subject: [PATCH 06/60] feat(dryrun): implement TezosNodeWriter.dryRunOperation --- src/chain/tezos/TezosNodeWriter.ts | 47 ++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/chain/tezos/TezosNodeWriter.ts b/src/chain/tezos/TezosNodeWriter.ts index 872681e1..705692d7 100644 --- a/src/chain/tezos/TezosNodeWriter.ts +++ b/src/chain/tezos/TezosNodeWriter.ts @@ -649,12 +649,8 @@ export namespace TezosNodeWriter { storageCost: resources.storageCost + fixedOriginationStorageCost } } - /** - * Dry run the given operation and return consumed resources. - * - * Note: Estimating an operation on an unrevealed account is not supported and will fail. Remember to prepend - * the Reveal operation if required. + * Dry run the given operation * * @param {string} server Tezos node to connect to * @param {string} chainid The chain ID to apply the operation on. @@ -666,16 +662,7 @@ export namespace TezosNodeWriter { chainid: string, ...operations: TezosP2PMessageTypes.Operation[] ): Promise<{ gas: number, storageCost: number }> { - const fake_signature = 'edsigu6xFLH2NpJ1VcYshpjW99Yc1TAL1m2XBqJyXrxcZQgBMo8sszw2zm626yjpA3pWMhjpsahLrWdmvX9cqhd4ZEUchuBuFYy'; - const fake_chainid = 'NetXdQprcVkpaWU'; - const fake_branch = 'BL94i2ShahPx3BoNs6tJdXDdGeoJ9ukwujUA2P8WJwULYNdimmq'; - - const response = await performPostRequest(server, `chains/${chainid}/blocks/head/helpers/scripts/run_operation`, { chain_id: fake_chainid, operation: { branch: fake_branch, contents: operations, signature: fake_signature } }); - const responseText = await response.text(); - - parseRPCError(responseText); - - const responseJSON = JSON.parse(responseText); + const responseJSON = dryRunOperation(server, chainid, ...operations); let gas = 0; let storageCost = 0; @@ -701,6 +688,36 @@ export namespace TezosNodeWriter { return { gas, storageCost }; } + /** + * Dry run the given operation and return consumed resources. + * + * Note: Estimating an operation on an unrevealed account is not supported and will fail. Remember to prepend + * the Reveal operation if required. + + * @param {string} server Tezos node to connect to + * @param {string} chainid The chain ID to apply the operation on. + * @param {TezosP2PMessageTypes.Operation} operations A set of operations to update. + * @returns {Promise} JSON-encoded response + */ + export async function dryRunOperation( + server: string, + chainid: string, + ...operations: TezosP2PMessageTypes.Operation[] + ): Promise { + const fake_signature = 'edsigu6xFLH2NpJ1VcYshpjW99Yc1TAL1m2XBqJyXrxcZQgBMo8sszw2zm626yjpA3pWMhjpsahLrWdmvX9cqhd4ZEUchuBuFYy'; + const fake_chainid = 'NetXdQprcVkpaWU'; + const fake_branch = 'BL94i2ShahPx3BoNs6tJdXDdGeoJ9ukwujUA2P8WJwULYNdimmq'; + + const response = await performPostRequest(server, `chains/${chainid}/blocks/head/helpers/scripts/run_operation`, { chain_id: fake_chainid, operation: { branch: fake_branch, contents: operations, signature: fake_signature } }); + const responseText = await response.text(); + + parseRPCError(responseText); + + const responseJSON = JSON.parse(responseText); + + return responseJSON; + } + /** * This function checks if the server response contains an error. There are multiple formats for errors coming * back from the server, this method attempts to normalized them for downstream parsing. From e99eb05327ace688a3b83c6563994b93ba37ca16 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 21:59:50 -0700 Subject: [PATCH 07/60] initial draft of token interactions --- package-lock.json | 2 +- src/chain/tezos/TezosNodeWriter.ts | 12 +- .../tezos/contracts/TezosContractUtils.ts | 15 +- .../tezos/contracts/WrappedTezosHelper.ts | 133 ++++++++++++++++++ src/index.ts | 1 + 5 files changed, 150 insertions(+), 13 deletions(-) create mode 100644 src/chain/tezos/contracts/WrappedTezosHelper.ts diff --git a/package-lock.json b/package-lock.json index aac67cba..b0dac061 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "conseiljs", - "version": "5.0.5", + "version": "5.0.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/chain/tezos/TezosNodeWriter.ts b/src/chain/tezos/TezosNodeWriter.ts index 17751441..94d7c629 100644 --- a/src/chain/tezos/TezosNodeWriter.ts +++ b/src/chain/tezos/TezosNodeWriter.ts @@ -444,6 +444,8 @@ export namespace TezosNodeWriter { parameterFormat: TezosTypes.TezosParameterFormat = TezosTypes.TezosParameterFormat.Micheline, offset: number = 54 ) { + console.log("STOR: " + storageLimit) + const counter = await TezosNodeReader.getCounterForAccount(server, keyStore.publicKeyHash) + 1; const transaction = constructContractInvocationOperation(keyStore.publicKeyHash, counter, contract, amount, fee, storageLimit, gasLimit, entrypoint, parameters, parameterFormat); @@ -721,12 +723,12 @@ export namespace TezosNodeWriter { // in CARTHAGE and prior protocols activation failures are caught in the first branch } else { errors = arr.map(r => r.contents) - .map(o => + .map(o => o.map(c => c.metadata.operation_result) - .concat(o.flatMap(c => c.metadata.internal_operation_results).filter(c => !!c).map(c => c.result)) - .map(r => parseRPCOperationResult(r)) - .filter(i => i.length > 0) - .join(', ')) + .concat(o.flatMap(c => c.metadata.internal_operation_results).filter(c => !!c).map(c => c.result)) + .map(r => parseRPCOperationResult(r)) + .filter(i => i.length > 0) + .join(', ')) .join(', '); } } catch (err) { diff --git a/src/chain/tezos/contracts/TezosContractUtils.ts b/src/chain/tezos/contracts/TezosContractUtils.ts index 1295d52b..238a926b 100644 --- a/src/chain/tezos/contracts/TezosContractUtils.ts +++ b/src/chain/tezos/contracts/TezosContractUtils.ts @@ -7,19 +7,20 @@ import { TezosNodeReader } from '../TezosNodeReader'; * */ export namespace TezosContractUtils { -/** - * 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. - */ + /** + * 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, expected: string): Promise { const contract = await TezosNodeReader.getAccountForBlock(server, 'head', 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'); + console.log("Expected: " + k) if (k !== expected) { throw new Error(`Contract code hash "${k}" doesn't match expected ${expected}`); } diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts new file mode 100644 index 00000000..88677f62 --- /dev/null +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -0,0 +1,133 @@ +import { JSONPath } from 'jsonpath-plus'; + +import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; +import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; +import { TezosMessageUtils } from '../TezosMessageUtil'; +import { TezosNodeReader } from '../TezosNodeReader'; +import { TezosNodeWriter } from '../TezosNodeWriter'; +import { TezosContractUtils } from './TezosContractUtils'; + +/** The expected checksum for the Wrapped Tezos contracts. */ +const CONTRACT_CHECKSUMS = { + token: 'd48b45bd77d2300026fe617c5ba7670e' + + // TODO(keefertaylor): Implement additional checksums for core and oven contracts here. +} + +/** The expected checksum for the Wrapped Tezos scripts. */ +const SCRIPT_CHECKSUMS = { + // TODO(keefertaylor): Compute this checksum correctly. + token: '0e3e137841a959521324b4ce20ca2df7' + + // TODO(keefertaylor): Implement additional checksums for core and oven contracts here. +} + +/** + * Interface for the Wrapped XTZ Token and Oven implementation. + * + * @see {@link https://forum.tezosagora.org/t/wrapped-tezos/2195|wXTZ on Tezos Agora} + * + * The token represented by these contracts trades with symbol 'WXTZ' and is specified with 10^-6 precision. Put + * simply, 1 XTZ = 1 WXTZ, and 0.000_001 XTZ = 1 Mutez = 0.000_001 WXTZ. + * + * Canonical Data: + * - Delphinet: + * - Token Contract: KT1JYf7xjCJAqFDfNpuump9woSMaapy1WcMY + * - Token Balances Map ID: 14566 + * - TODO(keefertaylor): Add core / oven contracts here. + * TODO(keefertaylor): Add additional data for mainnet here. + * + * @author Keefer Taylor, Staker Services Ltd + */ +export namespace WrappedTezosHelper { + /** + * Verifies that contract code for Wrapped Tezos matches the expected code. + * + * Note: This function processes contracts in the Micheline format. + * + * @param nodeUrl The URL of the Tezos node which serves data. + * @param tokenContractAddress The address of the token contract. + * @returns A boolean indicating if the code was the expected sum. + */ + export async function verifyDestination(nodeUrl: string, tokenContractAddress: string): Promise { + // TODO(keefertaylor): Verify checksums for core and oven contracts here. + return TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token); + } + + /** + * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. + * + * Note: This function processes scrips in Michelson format. + * + * @param tokenScript The address of the token contract. + * @returns A boolean indicating if the code was the expected sum. + */ + + export function verifyScript(tokenScript: string): boolean { + // TODO(keefertaylor): Verify checksums for core and oven scrips here. + return TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token); + } + + /** + * Get the balance of WXTZ tokens for an address. + * + * @param nodeUrl The URL of the Tezos node which serves data. + * @param mapId The ID of the BigMap which contains balances. + * @param address The address to fetch the token balance for. + */ + export async function getAccountBalance(server: string, mapid: number, address: string): Promise { + const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(address, 'address'), 'hex')); + const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); + + if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${address}`); } + + const numberString = JSONPath({ path: '$.int', json: mapResult }); + return Number(numberString); + } + + /** + * Transfer some WXTZ between addresses. + * + * @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 tokenContractAddress The address of the token contract. + * @param fee The fee to use. + * @param sourceAddress The address which will send tokens. + * @param destinationAddress The address which will receive tokens. + * @param amount The amount of tokens to send. + * @param gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @returns A string representing the transaction hash. + */ + export async function transferBalance( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + tokenContractAddress: string, + fee: number, + sourceAddress: string, + destinationAddress: string, + amount: number, + gasLimit: number, + storageLimit: number + ): Promise { + const parameters = `Pair "${sourceAddress}" (Pair "${destinationAddress}" ${amount})`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + tokenContractAddress, + 0, + fee, + storageLimit, + gasLimit, + 'transfer', + parameters, + TezosTypes.TezosParameterFormat.Michelson + ); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } +} diff --git a/src/index.ts b/src/index.ts index 486b98cb..4db46337 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,6 +25,7 @@ export * from './chain/tezos/contracts/tzip12/ChainlinkTokenHelper'; export * from './chain/tezos/contracts/tzip12/MultiAssetTokenHelper'; export * from './chain/tezos/contracts/tzip12/SingleAssetTokenHelper'; export * from './chain/tezos/contracts/TzbtcTokenHelper'; +export * from './chain/tezos/contracts/WrappedTezosHelper'; export * from "./reporting/tezos/TezosConseilClient"; From 32a42fc339b96d2ff7c562e638c7ab9f1c33e76f Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 22:05:49 -0700 Subject: [PATCH 08/60] revert file --- src/chain/tezos/TezosNodeWriter.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/chain/tezos/TezosNodeWriter.ts b/src/chain/tezos/TezosNodeWriter.ts index 94d7c629..17751441 100644 --- a/src/chain/tezos/TezosNodeWriter.ts +++ b/src/chain/tezos/TezosNodeWriter.ts @@ -444,8 +444,6 @@ export namespace TezosNodeWriter { parameterFormat: TezosTypes.TezosParameterFormat = TezosTypes.TezosParameterFormat.Micheline, offset: number = 54 ) { - console.log("STOR: " + storageLimit) - const counter = await TezosNodeReader.getCounterForAccount(server, keyStore.publicKeyHash) + 1; const transaction = constructContractInvocationOperation(keyStore.publicKeyHash, counter, contract, amount, fee, storageLimit, gasLimit, entrypoint, parameters, parameterFormat); @@ -723,12 +721,12 @@ export namespace TezosNodeWriter { // in CARTHAGE and prior protocols activation failures are caught in the first branch } else { errors = arr.map(r => r.contents) - .map(o => + .map(o => o.map(c => c.metadata.operation_result) - .concat(o.flatMap(c => c.metadata.internal_operation_results).filter(c => !!c).map(c => c.result)) - .map(r => parseRPCOperationResult(r)) - .filter(i => i.length > 0) - .join(', ')) + .concat(o.flatMap(c => c.metadata.internal_operation_results).filter(c => !!c).map(c => c.result)) + .map(r => parseRPCOperationResult(r)) + .filter(i => i.length > 0) + .join(', ')) .join(', '); } } catch (err) { From 7f40cff9a7c9db3bba44ff29d333927e45904150 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 22:06:26 -0700 Subject: [PATCH 09/60] revert another file --- src/chain/tezos/contracts/TezosContractUtils.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/chain/tezos/contracts/TezosContractUtils.ts b/src/chain/tezos/contracts/TezosContractUtils.ts index 238a926b..1295d52b 100644 --- a/src/chain/tezos/contracts/TezosContractUtils.ts +++ b/src/chain/tezos/contracts/TezosContractUtils.ts @@ -7,20 +7,19 @@ import { TezosNodeReader } from '../TezosNodeReader'; * */ export namespace TezosContractUtils { - /** - * 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. - */ +/** + * 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, expected: string): Promise { const contract = await TezosNodeReader.getAccountForBlock(server, 'head', 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'); - console.log("Expected: " + k) if (k !== expected) { throw new Error(`Contract code hash "${k}" doesn't match expected ${expected}`); } From 635088c31559c7dc03fae29f8c3b3d3bd34d199b Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 22:07:33 -0700 Subject: [PATCH 10/60] export for web --- src/index-web.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index-web.ts b/src/index-web.ts index 2d867cab..4f0660a6 100644 --- a/src/index-web.ts +++ b/src/index-web.ts @@ -20,6 +20,7 @@ export * from './chain/tezos/contracts/tzip12/ChainlinkTokenHelper'; export * from './chain/tezos/contracts/tzip12/MultiAssetTokenHelper'; export * from './chain/tezos/contracts/tzip12/SingleAssetTokenHelper'; export * from './chain/tezos/contracts/TzbtcTokenHelper'; +export * from './chain/tezos/contracts/WrappedTezosHelper'; export * from './reporting/tezos/TezosConseilClient'; export * from './reporting/ConseilDataClient'; From 35cf58e54f99cded0f1a1036157353239bb4249a Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 21:14:24 -0800 Subject: [PATCH 11/60] Update WrappedTezosHelper.ts --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 88677f62..77da0b85 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -59,7 +59,7 @@ export namespace WrappedTezosHelper { * * Note: This function processes scrips in Michelson format. * - * @param tokenScript The address of the token contract. + * @param tokenScript The script of the token contract. * @returns A boolean indicating if the code was the expected sum. */ From dd16ba110b7dc31787b1a15ddc21be6b852d613c Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 22:49:41 -0700 Subject: [PATCH 12/60] oven interactions --- .../tezos/contracts/WrappedTezosHelper.ts | 127 ++++++++++++++++-- 1 file changed, 117 insertions(+), 10 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 88677f62..17854b9c 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -9,17 +9,20 @@ import { TezosContractUtils } from './TezosContractUtils'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { - token: 'd48b45bd77d2300026fe617c5ba7670e' + token: 'd48b45bd77d2300026fe617c5ba7670e', + oven: '5e3c30607da21a0fc30f7be61afb15c7' - // TODO(keefertaylor): Implement additional checksums for core and oven contracts here. + // TODO(keefertaylor): Implement additional checksums for core contract here. } /** The expected checksum for the Wrapped Tezos scripts. */ const SCRIPT_CHECKSUMS = { // TODO(keefertaylor): Compute this checksum correctly. - token: '0e3e137841a959521324b4ce20ca2df7' + token: '', + // TODO(keefertaylor): Compute this checksum correctly. + oven: '', - // TODO(keefertaylor): Implement additional checksums for core and oven contracts here. + // TODO(keefertaylor): Implement additional checksums for core script here. } /** @@ -47,11 +50,19 @@ 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. * @returns A boolean indicating if the code was the expected sum. */ - export async function verifyDestination(nodeUrl: string, tokenContractAddress: string): Promise { - // TODO(keefertaylor): Verify checksums for core and oven contracts here. - return TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token); + export async function verifyDestination( + nodeUrl: string, + tokenContractAddress: string, + ovenContractAddress: 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) + + return tokenMatched && ovenMatched } /** @@ -59,13 +70,17 @@ export namespace WrappedTezosHelper { * * Note: This function processes scrips in Michelson format. * - * @param tokenScript The address of the token contract. + * @param tokenScript The script of the token contract. + * @param ovenScript The script of an oven contract. * @returns A boolean indicating if the code was the expected sum. */ export function verifyScript(tokenScript: string): boolean { - // TODO(keefertaylor): Verify checksums for core and oven scrips here. - return TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token); + // TODO(keefertaylor): Verify checksums for core script here. + const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) + const ovenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.oven) + + return tokenMatched && ovenMatched } /** @@ -130,4 +145,96 @@ export namespace WrappedTezosHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + + /** + * Deposit XTZ into an oven to mint WXTZ. + * + * WXTZ will be minted for the owner of the oven, *not* the source address. This allows bakers + * to payout delegated ovens. + * + * @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 ovenAddress The address of the oven contract. + * @param fee The fee to use. + * @param amountMutez The amount of XTZ to deposit, specified in mutez. + * @param gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @returns A string representing the transaction hash. + */ + export async function depositToOven( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + ovenAddress: string, + fee: number, + amountMutez: number, + gasLimit: number, + storageLimit: number + ): Promise { + const parameters = 'Unit' + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + ovenAddress, + amountMutez, + fee, + storageLimit, + gasLimit, + '', + parameters, + TezosTypes.TezosParameterFormat.Michelson + ) + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + /** + * Withdraw XTZ from an oven by repaying WXTZ. + * + * This operation will fail if: + * - The sending account is not the oven owner. + * - The sending account does not possess the equivalent amount of WXTZ to the withdrawal amount + * - The oven has less XTZ in it than is requested to be withdrawn. + * + * @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 ovenAddress The address of the oven contract. + * @param fee The fee to use. + * @param amountMutez The amount of XTZ to withdraw, specified in mutez. + * @param gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @returns A string representing the transaction hash. + */ + export async function withdrawFromOven( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + ovenAddress: string, + fee: number, + amountMutez: number, + gasLimit: number, + storageLimit: number + ): Promise { + const parameters = `${amountMutez}` + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + ovenAddress, + 0, + fee, + storageLimit, + gasLimit, + 'withdraw', + parameters, + TezosTypes.TezosParameterFormat.Michelson + ) + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } } From c0f25675fc8606d5af7c3c88f71422350a9aa328 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Tue, 24 Nov 2020 23:38:25 -0700 Subject: [PATCH 13/60] 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 14/60] 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 8e8a9f65378309ce11103da0ea9ebcc3c571849b Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Wed, 25 Nov 2020 01:45:49 -0500 Subject: [PATCH 15/60] - added WrappedTezosHelper.getSimpleStorage and related types --- .../tezos/contracts/WrappedTezosHelper.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 77da0b85..65501a85 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -22,6 +22,22 @@ const SCRIPT_CHECKSUMS = { // TODO(keefertaylor): Implement additional checksums for core and oven contracts here. } +export interface WrappedTezosStorage { + balanceMap: number; + approvalsMap: number; + supply: number; + administrator: string; + paused: boolean; + pauseGuardian: string; + outcomeMap: number; + swapMap: number; +} + +export interface WrappedTezosBalanceRecord { } +export interface WrappedTezosApprovalRecord { } +export interface WrappedTezosOutcomeRecord { } +export interface WrappedTezosSwapRecord { } + /** * Interface for the Wrapped XTZ Token and Oven implementation. * @@ -68,6 +84,28 @@ export namespace WrappedTezosHelper { return TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token); } + /** + * + * @param server + * @param address + */ + export async function getSimpleStorage(server: string, address: string): Promise { + const storageResult = await TezosNodeReader.getContractStorage(server, address); + + console.log(JSON.stringify(storageResult)); + + return { + balanceMap: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[0].int', json: storageResult })[0]), + approvalsMap: Number(JSONPath({ path: '$.args[1].args[0].args[0].args[1].int', json: storageResult })[0]), + supply: Number(JSONPath({ path: '$.args[1].args[1].args[1].int', json: storageResult })[0]), + administrator: JSONPath({ path: '$.args[1].args[0].args[0].args[0].string', json: storageResult })[0], + paused: (JSONPath({ path: '$.args[1].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), + pauseGuardian: JSONPath({ path: '$.args[1].args[0].args[1].args[1].string', json: storageResult })[0], + outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), + swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) + }; + } + /** * Get the balance of WXTZ tokens for an address. * From 2979f64404b668ec80e2ba21fd8e09578b6f2931 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 09:40:33 -0700 Subject: [PATCH 16/60] 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 17/60] 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, From 1e78d4871ec7ced06c01d35648ff38f7fd65d822 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 10:05:28 -0700 Subject: [PATCH 18/60] delegate / clear delegate functions --- .../tezos/contracts/WrappedTezosHelper.ts | 123 +++++++++++++----- 1 file changed, 94 insertions(+), 29 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index a2e1fa46..435d6910 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -113,40 +113,19 @@ export namespace WrappedTezosHelper { return tokenMatched && ovenMatched && coreMatched } - /** - * - * @param server - * @param address - */ - export async function getSimpleStorage(server: string, address: string): Promise { - const storageResult = await TezosNodeReader.getContractStorage(server, address); - - console.log(JSON.stringify(storageResult)); - - return { - balanceMap: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[0].int', json: storageResult })[0]), - approvalsMap: Number(JSONPath({ path: '$.args[1].args[0].args[0].args[1].int', json: storageResult })[0]), - supply: Number(JSONPath({ path: '$.args[1].args[1].args[1].int', json: storageResult })[0]), - administrator: JSONPath({ path: '$.args[1].args[0].args[0].args[0].string', json: storageResult })[0], - paused: (JSONPath({ path: '$.args[1].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), - pauseGuardian: JSONPath({ path: '$.args[1].args[0].args[1].args[1].string', json: storageResult })[0], - outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), - swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) - }; - } - /** * Get the balance of WXTZ tokens for an address. * * @param nodeUrl The URL of the Tezos node which serves data. * @param mapId The ID of the BigMap which contains balances. - * @param address The address to fetch the token balance for. + * @param account The account to fetch the token balance for. + * @returns The balance of the account. */ - export async function getAccountBalance(server: string, mapid: number, address: string): Promise { - const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(address, 'address'), 'hex')); + export async function getAccountBalance(server: string, mapid: number, account: string): Promise { + const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); - if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${address}`); } + if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${account}`); } const numberString = JSONPath({ path: '$.int', json: mapResult }); return Number(numberString); @@ -165,7 +144,7 @@ export namespace WrappedTezosHelper { * @param amount The amount of tokens to send. * @param gasLimit The gas limit to use. * @param storageLimit The storage limit to use. - * @returns A string representing the transaction hash. + * @returns A string representing the operation hash. */ export async function transferBalance( nodeUrl: string, @@ -212,7 +191,7 @@ export namespace WrappedTezosHelper { * @param amountMutez The amount of XTZ to deposit, specified in mutez. * @param gasLimit The gas limit to use. * @param storageLimit The storage limit to use. - * @returns A string representing the transaction hash. + * @returns A string representing the operation hash. */ export async function depositToOven( nodeUrl: string, @@ -259,7 +238,7 @@ export namespace WrappedTezosHelper { * @param amountMutez The amount of XTZ to withdraw, specified in mutez. * @param gasLimit The gas limit to use. * @param storageLimit The storage limit to use. - * @returns A string representing the transaction hash. + * @returns A string representing the operation hash. */ export async function withdrawFromOven( nodeUrl: string, @@ -325,4 +304,90 @@ export namespace WrappedTezosHelper { ovenAddress } } + + /** + * Set the baker for an oven. + * + * This operation will fail if the sender is not the oven owner. + * + * @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 gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @param ovenAddress The address of the oven contract. + * @param bakerAddress The address of the baker for the oven. + * @returns A string representing the operation hash. + */ + export async function setOvenBaker( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + fee: number, + gasLimit: number, + storageLimit: number, + ovenAddress: string, + bakerAddress: string + ): Promise { + const parameters = `Some "${bakerAddress}"` + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + ovenAddress, + 0, + fee, + storageLimit, + gasLimit, + 'setDelegate', + parameters, + TezosTypes.TezosParameterFormat.Michelson + ) + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } + + /** + * Clear the baker for an oven. + * + * This operation will fail if the sender is not the oven owner. + * + * @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 gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @param ovenAddress The address of the oven contract. + * @returns A string representing the operation hash. + */ + export async function clearOvenBaker( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + fee: number, + gasLimit: number, + storageLimit: number, + ovenAddress: string, + ): Promise { + const parameters = `None` + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + ovenAddress, + 0, + fee, + storageLimit, + gasLimit, + 'setDelegate', + parameters, + TezosTypes.TezosParameterFormat.Michelson + ) + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } } From a4bfa2f9fe1aaeaf79e16c3dda38926308b881d4 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 10:11:40 -0700 Subject: [PATCH 19/60] revert changes in flight --- src/chain/tezos/TezosMessageUtil.ts | 44 ----------------------------- 1 file changed, 44 deletions(-) diff --git a/src/chain/tezos/TezosMessageUtil.ts b/src/chain/tezos/TezosMessageUtil.ts index 6ac3d10a..3acbcc74 100644 --- a/src/chain/tezos/TezosMessageUtil.ts +++ b/src/chain/tezos/TezosMessageUtil.ts @@ -552,48 +552,4 @@ 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 - } } From 23eefafab83059035e8ae01f83137bf8100dd5d8 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 10:12:51 -0700 Subject: [PATCH 20/60] revert openopen --- .../tezos/contracts/WrappedTezosHelper.ts | 56 ++----------------- 1 file changed, 5 insertions(+), 51 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 435d6910..e4839976 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -11,8 +11,9 @@ import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { token: 'd48b45bd77d2300026fe617c5ba7670e', - oven: '5e3c30607da21a0fc30f7be61afb15c7', - core: '7b9b5b7e7f0283ff6388eb783e23c452' + oven: '5e3c30607da21a0fc30f7be61afb15c7' + + // TODO(keefertaylor): Implement additional checksums for core contract here. } /** The expected checksum for the Wrapped Tezos scripts. */ @@ -20,20 +21,9 @@ const SCRIPT_CHECKSUMS = { // TODO(keefertaylor): Compute this checksum correctly. token: '', // TODO(keefertaylor): Compute this checksum correctly. - oven: '', - // TODO(keefertaylor): Compute this checksum correctly. - core: '' -} + oven: '' -/** - * Property bag containing the results of opening an oven. - */ -export type OpenOvenResult = { - // The operation hash of the request to open an oven. - operationHash: string - - // The address of the new oven contract. - ovenAddress: string + // TODO(keefertaylor): Implement additional checksums for core script here. } export interface WrappedTezosStorage { @@ -269,42 +259,6 @@ 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 = TezosMessageUtils.calculateContractAddress(operationHash, 0) - return { - operationHash, - ovenAddress - } - } - /** * Set the baker for an oven. * From b71e8b87a1ba99d4300210bc8ac73b6e2d279394 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 10:14:02 -0700 Subject: [PATCH 21/60] more reverts --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index e4839976..17012d81 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -6,7 +6,6 @@ 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 = { @@ -21,9 +20,9 @@ const SCRIPT_CHECKSUMS = { // TODO(keefertaylor): Compute this checksum correctly. token: '', // TODO(keefertaylor): Compute this checksum correctly. - oven: '' + oven: '', - // TODO(keefertaylor): Implement additional checksums for core script here. + // TODO(keefertaylor): Implement additional checksums for core script here. } export interface WrappedTezosStorage { @@ -68,7 +67,6 @@ 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( @@ -77,11 +75,11 @@ export namespace WrappedTezosHelper { 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 && coreMatched + return tokenMatched && ovenMatched } /** @@ -91,16 +89,15 @@ 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, ovenScript, string, coreScript: string): boolean { + // TODO(keefertaylor): Verify checksums for core script here. const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven) - const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core) - return tokenMatched && ovenMatched && coreMatched + return tokenMatched && ovenMatched } /** From 431b4f186be7ea1d57336f3e3d2e639ce3193fe1 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 10:14:37 -0700 Subject: [PATCH 22/60] more reverts --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 17012d81..f978cee1 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -72,8 +72,7 @@ export namespace WrappedTezosHelper { export async function verifyDestination( nodeUrl: string, tokenContractAddress: string, - ovenContractAddress: string, - coreContractAddress: string + ovenContractAddress: string ): Promise { // TODO(keefertaylor): Verify checksums for core contract here. const tokenMatched = TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token) @@ -92,7 +91,7 @@ export namespace WrappedTezosHelper { * @returns A boolean indicating if the code was the expected sum. */ - export function verifyScript(tokenScript: string, ovenScript, string, coreScript: string): boolean { + export function verifyScript(tokenScript: string, ovenScript: string): boolean { // TODO(keefertaylor): Verify checksums for core script here. const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven) From 1c551a32e4595ee65b302a77cc86f3b3bd330d05 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 10:16:28 -0700 Subject: [PATCH 23/60] more fixes --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index f978cee1..94796ea5 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -90,7 +90,6 @@ export namespace WrappedTezosHelper { * @param ovenScript The script of an oven contract. * @returns A boolean indicating if the code was the expected sum. */ - export function verifyScript(tokenScript: string, ovenScript: string): boolean { // TODO(keefertaylor): Verify checksums for core script here. const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) From 29476b4817c0a60d4bcb40ebb3bc71295faa09ae Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 11:32:59 -0700 Subject: [PATCH 24/60] list ovens function --- .../tezos/contracts/WrappedTezosHelper.ts | 121 ++++++++++++------ src/reporting/tezos/TezosConseilClient.ts | 24 ++-- 2 files changed, 100 insertions(+), 45 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 88d054ff..4c1755c8 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -6,13 +6,15 @@ import { TezosMessageUtils } from '../TezosMessageUtil'; import { TezosNodeReader } from '../TezosNodeReader'; import { TezosNodeWriter } from '../TezosNodeWriter'; import { TezosContractUtils } from './TezosContractUtils'; +import { TezosConseilClient } from '../../../reporting/tezos/TezosConseilClient' +import { ConseilServerInfo } from 'types/conseil/QueryTypes'; +import { ContractMapDetailsItem } from 'types/conseil/ConseilTezosTypes'; /** 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,8 @@ const SCRIPT_CHECKSUMS = { token: '', // TODO(keefertaylor): Compute this checksum correctly. oven: '', - - // TODO(keefertaylor): Implement additional checksums for core script here. + // TODO(keefertaylor): Compute this checksum correctly. + core: '' } export interface WrappedTezosStorage { @@ -41,6 +43,14 @@ export interface WrappedTezosApprovalRecord { } export interface WrappedTezosOutcomeRecord { } export interface WrappedTezosSwapRecord { } +/** + * Types for the Oven Map . + * + * Key: The oven's address. + * Value: The oven owner's address. + */ +export type OvenMapSchema = { key: string, value: string } + /** * Interface for the Wrapped XTZ Token and Oven implementation. * @@ -52,8 +62,9 @@ export interface WrappedTezosSwapRecord { } * Canonical Data: * - Delphinet: * - Token Contract: KT1JYf7xjCJAqFDfNpuump9woSMaapy1WcMY + * - Core Contract: KT1S98ELFTo6mdMBqhAVbGgKAVgLbdPP3AX8 * - Token Balances Map ID: 14566 - * - TODO(keefertaylor): Add core / oven contracts here. + * - Oven List Map ID: 14569 * TODO(keefertaylor): Add additional data for mainnet here. * * @author Keefer Taylor, Staker Services Ltd @@ -67,18 +78,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 } /** @@ -88,37 +101,19 @@ 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 - } - - /** - * - * @param server - * @param address - */ - export async function getSimpleStorage(server: string, address: string): Promise { - const storageResult = await TezosNodeReader.getContractStorage(server, address); - - console.log(JSON.stringify(storageResult)); - - return { - balanceMap: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[0].int', json: storageResult })[0]), - approvalsMap: Number(JSONPath({ path: '$.args[1].args[0].args[0].args[1].int', json: storageResult })[0]), - supply: Number(JSONPath({ path: '$.args[1].args[1].args[1].int', json: storageResult })[0]), - administrator: JSONPath({ path: '$.args[1].args[0].args[0].args[0].string', json: storageResult })[0], - paused: (JSONPath({ path: '$.args[1].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), - pauseGuardian: JSONPath({ path: '$.args[1].args[0].args[1].args[1].string', json: storageResult })[0], - outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), - swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) - }; + return tokenMatched && ovenMatched && coreMatched } /** @@ -275,4 +270,58 @@ export namespace WrappedTezosHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } + + /** + * Retrieve a list of all oven addresses a user owns. + * + * @param serverInfo Connection info for Conseil. + * @param coreContractAddress The core contract address + * @param ovenOwner The oven owner to search for + * @param ovenListBigMapId The BigMap ID of the oven list. + */ + export async function listOvens( + serverInfo: ConseilServerInfo, + coreContractAddress: string, + ovenOwner: string, + ovenListBigMapId: number + ): Promise> { + // Fetch map data. + const mapData = await TezosConseilClient.getBigMapData(serverInfo, coreContractAddress) + if (mapData === undefined) { + throw new Error("Could not fetch map data!") + } + + // Find the Map that contains the oven list. + const { maps } = mapData + let ovenListMap: ContractMapDetailsItem | undefined = undefined + for (let i = 0; i < maps.length; i++) { + if (maps[i].definition.index === ovenListBigMapId) { + ovenListMap = maps[i] + break + } + } + if (ovenListMap === undefined) { + throw new Error("Could not find specified map ID!") + } + + // Conseil reports addresses as quoted michelson encoded hex prefixed + // with '0x'. Normalize these to base58check encoded addresses. + const { content } = ovenListMap + const normalizedOvenList: Array = content.map((oven: OvenMapSchema) => { + return { + key: TezosMessageUtils.readAddress(oven.key.replace(/\"/g, '').replace(/\n/, '').replace("0x", "")), + value: TezosMessageUtils.readAddress(oven.value.replace(/\"/g, '').replace(/\n/, '').replace("0x", "")) + } + }) + + // Filter oven list for ovens belonging to the owner. + const ownedOvens = normalizedOvenList.filter((oven: OvenMapSchema): boolean => { + return ovenOwner === oven.value + }) + + // Map filtered array to only contain oven addresses. + return ownedOvens.map((oven: OvenMapSchema) => { + return oven.key + }) + } } diff --git a/src/reporting/tezos/TezosConseilClient.ts b/src/reporting/tezos/TezosConseilClient.ts index 6a963595..3d6325cd 100644 --- a/src/reporting/tezos/TezosConseilClient.ts +++ b/src/reporting/tezos/TezosConseilClient.ts @@ -221,8 +221,8 @@ export namespace TezosConseilClient { let currentLevel = initialLevel; let operationQuery = ConseilQueryBuilder.blankQuery(); - operationQuery = ConseilQueryBuilder.addPredicate(operationQuery , 'operation_group_hash', ConseilOperator.EQ, [hash], false); - operationQuery = ConseilQueryBuilder.addPredicate(operationQuery , 'timestamp', ConseilOperator.AFTER, [startTime], false); + operationQuery = ConseilQueryBuilder.addPredicate(operationQuery, 'operation_group_hash', ConseilOperator.EQ, [hash], false); + operationQuery = ConseilQueryBuilder.addPredicate(operationQuery, 'timestamp', ConseilOperator.AFTER, [startTime], false); operationQuery = ConseilQueryBuilder.setLimit(operationQuery, 1); while (initialLevel + duration > currentLevel) { @@ -293,22 +293,28 @@ export namespace TezosConseilClient { if (ownerResult.length < 1) { return undefined; } + console.log("Got an owner result") + const definitionQuery = ConseilQueryBuilder.setLimit(ConseilQueryBuilder.addPredicate(ConseilQueryBuilder.blankQuery(), 'big_map_id', (ownerResult.length > 1 ? ConseilOperator.IN : ConseilOperator.EQ), ownerResult.map(r => r.big_map_id), false), 100); const definitionResult = await getTezosEntityData(serverInfo, serverInfo.network, 'big_maps', definitionQuery); + console.log("Got def result " + JSON.stringify(definitionResult)) + const contentQuery = ConseilQueryBuilder.setLimit(ConseilQueryBuilder.addFields(ConseilQueryBuilder.addPredicate(ConseilQueryBuilder.blankQuery(), 'big_map_id', (ownerResult.length > 1 ? ConseilOperator.IN : ConseilOperator.EQ), ownerResult.map(r => r.big_map_id), false), 'big_map_id', 'key', 'value'), 1000); const contentResult = await getTezosEntityData(serverInfo, serverInfo.network, 'big_map_contents', contentQuery); + console.log("Got content result " + JSON.stringify(contentResult)) + let maps: ContractMapDetailsItem[] = []; for (const d of definitionResult) { const definition = { index: Number(d['big_map_id']), key: d['key_type'], value: d['value_type'] }; let content: { key: string, value: string }[] = []; - for(const c of contentResult.filter(r => r['big_map_id'] === definition.index)) { - content.push({ key: JSON.stringify(c['key']), value: JSON.stringify(c['value'])}); + for (const c of contentResult.filter(r => r['big_map_id'] === definition.index)) { + content.push({ key: JSON.stringify(c['key']), value: JSON.stringify(c['value']) }); } - maps.push({definition, content}); + maps.push({ definition, content }); } return { contract, maps }; @@ -371,8 +377,8 @@ export namespace TezosConseilClient { if (i === 1) { return a && c['level'] === initialLevel - && c['hash'] === initialHash - && c['predecessor'] === blocks[i - 1]['hash']; + && c['hash'] === initialHash + && c['predecessor'] === blocks[i - 1]['hash']; } if (i === 0) { @@ -403,12 +409,12 @@ export namespace TezosConseilClient { export function getEntityQueryForId(id: string | number): { entity: string, query: ConseilQuery } { let q = ConseilQueryBuilder.setLimit(ConseilQueryBuilder.blankQuery(), 1); - if (typeof id === 'number') { + if (typeof id === 'number') { const n = Number(id); if (n < 0) { throw new Error('Invalid numeric id parameter'); } return { entity: BLOCKS, query: ConseilQueryBuilder.addPredicate(q, 'level', ConseilOperator.EQ, [id], false) }; - } else if (typeof id === 'string') { + } else if (typeof id === 'string') { const s = String(id); if (s.startsWith('tz1') || s.startsWith('tz2') || s.startsWith('tz3') || s.startsWith('KT1')) { From d963103be174c8508c31b7095e0430e9609d6e00 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 11:36:25 -0700 Subject: [PATCH 25/60] revert some debugging --- src/reporting/tezos/TezosConseilClient.ts | 24 +++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/reporting/tezos/TezosConseilClient.ts b/src/reporting/tezos/TezosConseilClient.ts index 3d6325cd..6a963595 100644 --- a/src/reporting/tezos/TezosConseilClient.ts +++ b/src/reporting/tezos/TezosConseilClient.ts @@ -221,8 +221,8 @@ export namespace TezosConseilClient { let currentLevel = initialLevel; let operationQuery = ConseilQueryBuilder.blankQuery(); - operationQuery = ConseilQueryBuilder.addPredicate(operationQuery, 'operation_group_hash', ConseilOperator.EQ, [hash], false); - operationQuery = ConseilQueryBuilder.addPredicate(operationQuery, 'timestamp', ConseilOperator.AFTER, [startTime], false); + operationQuery = ConseilQueryBuilder.addPredicate(operationQuery , 'operation_group_hash', ConseilOperator.EQ, [hash], false); + operationQuery = ConseilQueryBuilder.addPredicate(operationQuery , 'timestamp', ConseilOperator.AFTER, [startTime], false); operationQuery = ConseilQueryBuilder.setLimit(operationQuery, 1); while (initialLevel + duration > currentLevel) { @@ -293,28 +293,22 @@ export namespace TezosConseilClient { if (ownerResult.length < 1) { return undefined; } - console.log("Got an owner result") - const definitionQuery = ConseilQueryBuilder.setLimit(ConseilQueryBuilder.addPredicate(ConseilQueryBuilder.blankQuery(), 'big_map_id', (ownerResult.length > 1 ? ConseilOperator.IN : ConseilOperator.EQ), ownerResult.map(r => r.big_map_id), false), 100); const definitionResult = await getTezosEntityData(serverInfo, serverInfo.network, 'big_maps', definitionQuery); - console.log("Got def result " + JSON.stringify(definitionResult)) - const contentQuery = ConseilQueryBuilder.setLimit(ConseilQueryBuilder.addFields(ConseilQueryBuilder.addPredicate(ConseilQueryBuilder.blankQuery(), 'big_map_id', (ownerResult.length > 1 ? ConseilOperator.IN : ConseilOperator.EQ), ownerResult.map(r => r.big_map_id), false), 'big_map_id', 'key', 'value'), 1000); const contentResult = await getTezosEntityData(serverInfo, serverInfo.network, 'big_map_contents', contentQuery); - console.log("Got content result " + JSON.stringify(contentResult)) - let maps: ContractMapDetailsItem[] = []; for (const d of definitionResult) { const definition = { index: Number(d['big_map_id']), key: d['key_type'], value: d['value_type'] }; let content: { key: string, value: string }[] = []; - for (const c of contentResult.filter(r => r['big_map_id'] === definition.index)) { - content.push({ key: JSON.stringify(c['key']), value: JSON.stringify(c['value']) }); + for(const c of contentResult.filter(r => r['big_map_id'] === definition.index)) { + content.push({ key: JSON.stringify(c['key']), value: JSON.stringify(c['value'])}); } - maps.push({ definition, content }); + maps.push({definition, content}); } return { contract, maps }; @@ -377,8 +371,8 @@ export namespace TezosConseilClient { if (i === 1) { return a && c['level'] === initialLevel - && c['hash'] === initialHash - && c['predecessor'] === blocks[i - 1]['hash']; + && c['hash'] === initialHash + && c['predecessor'] === blocks[i - 1]['hash']; } if (i === 0) { @@ -409,12 +403,12 @@ export namespace TezosConseilClient { export function getEntityQueryForId(id: string | number): { entity: string, query: ConseilQuery } { let q = ConseilQueryBuilder.setLimit(ConseilQueryBuilder.blankQuery(), 1); - if (typeof id === 'number') { + if (typeof id === 'number') { const n = Number(id); if (n < 0) { throw new Error('Invalid numeric id parameter'); } return { entity: BLOCKS, query: ConseilQueryBuilder.addPredicate(q, 'level', ConseilOperator.EQ, [id], false) }; - } else if (typeof id === 'string') { + } else if (typeof id === 'string') { const s = String(id); if (s.startsWith('tz1') || s.startsWith('tz2') || s.startsWith('tz3') || s.startsWith('KT1')) { From 9dd9e6f8d19c55cc44c2a85977887e10280c38e0 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 17:26:11 -0700 Subject: [PATCH 26/60] more merges --- src/chain/tezos/TezosMessageUtil.ts | 44 +++++++++++++++++++ .../tezos/contracts/WrappedTezosHelper.ts | 38 +++++++++++----- 2 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/chain/tezos/TezosMessageUtil.ts b/src/chain/tezos/TezosMessageUtil.ts index 3acbcc74..5d541338 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 ef0f58a5..5133dcaf 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -6,13 +6,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 +21,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 } export interface WrappedTezosStorage { @@ -67,18 +78,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 } /** @@ -88,14 +101,19 @@ 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, ovenScript: 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(ovenScript, SCRIPT_CHECKSUMS.oven) + const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core) - return tokenMatched && ovenMatched + return tokenMatched && ovenMatched && coreMatched } /** From 29c41e21ea41925de1dfb213dffc33520010e5ea Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 17:28:32 -0700 Subject: [PATCH 27/60] revert --- src/chain/tezos/TezosMessageUtil.ts | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/chain/tezos/TezosMessageUtil.ts b/src/chain/tezos/TezosMessageUtil.ts index 5d541338..6ac3d10a 100644 --- a/src/chain/tezos/TezosMessageUtil.ts +++ b/src/chain/tezos/TezosMessageUtil.ts @@ -553,17 +553,17 @@ 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. + /** + * 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. + // 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. + // Merge the decoded buffer with the operation prefix. let decodedAndOperationPrefix: Array = [] for (let i = 0; i < decoded.length; i++) { decodedAndOperationPrefix.push(decoded[i]) @@ -575,19 +575,19 @@ export namespace TezosMessageUtils { index & 0x000000ff, ]) - // Hash and encode. + // Hash and encode. const hash = blakejs.blake2b(new Uint8Array(decodedAndOperationPrefix), null, 20) - const smartContractAddressPrefix = new Uint8Array([2, 90, 121]) // KT1 + 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. + /** + * 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) From 447055091551f4c2047d2a4fcc3db4075ee8d7e3 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 17:30:06 -0700 Subject: [PATCH 28/60] restore function --- .../tezos/contracts/WrappedTezosHelper.ts | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 5133dcaf..711f66fa 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -21,15 +21,15 @@ const SCRIPT_CHECKSUMS = { token: '', // TODO(keefertaylor): Compute this checksum correctly. oven: '', - // TODO(keefertaylor): Compute this checksum correctly. + // TODO(keefertaylor): Compute this checksum correctly. core: '' } -/** - * Property bag containing the results of opening an oven. +/** + * Property bag containing the results of opening an oven. */ export type OpenOvenResult = { - // The operation hash of the request to open an oven. + // The operation hash of the request to open an oven. operationHash: string // The address of the new oven contract. @@ -78,7 +78,7 @@ 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. * + * @param coreContractAddress The address of the core contract. * @returns A boolean indicating if the code was the expected sum. */ export async function verifyDestination( @@ -116,6 +116,28 @@ export namespace WrappedTezosHelper { return tokenMatched && ovenMatched && coreMatched } + /** + * + * @param server + * @param address + */ + export async function getSimpleStorage(server: string, address: string): Promise { + const storageResult = await TezosNodeReader.getContractStorage(server, address); + + console.log(JSON.stringify(storageResult)); + + return { + balanceMap: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[0].int', json: storageResult })[0]), + approvalsMap: Number(JSONPath({ path: '$.args[1].args[0].args[0].args[1].int', json: storageResult })[0]), + supply: Number(JSONPath({ path: '$.args[1].args[1].args[1].int', json: storageResult })[0]), + administrator: JSONPath({ path: '$.args[1].args[0].args[0].args[0].string', json: storageResult })[0], + paused: (JSONPath({ path: '$.args[1].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), + pauseGuardian: JSONPath({ path: '$.args[1].args[0].args[1].args[1].string', json: storageResult })[0], + outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), + swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) + }; + } + /** * Get the balance of WXTZ tokens for an address. * From 148e04a6bf6bdfd38765f308a10910d537f05848 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 17:34:44 -0700 Subject: [PATCH 29/60] polish --- .../tezos/contracts/WrappedTezosHelper.ts | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 711f66fa..e8fe9f36 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -78,7 +78,7 @@ 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. + * @param coreContractAddress The address of the core contract. * @returns A boolean indicating if the code was the expected sum. */ export async function verifyDestination( @@ -116,10 +116,10 @@ export namespace WrappedTezosHelper { return tokenMatched && ovenMatched && coreMatched } - /** - * - * @param server - * @param address + /** + * + * @param server + * @param address */ export async function getSimpleStorage(server: string, address: string): Promise { const storageResult = await TezosNodeReader.getContractStorage(server, address); @@ -294,7 +294,7 @@ export namespace WrappedTezosHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } - /** + /** * Open a new oven. * * The oven's owner is assigned to the sender's address. @@ -345,20 +345,20 @@ export namespace WrappedTezosHelper { } /** - * Set the baker for an oven. - * - * This operation will fail if the sender is not the oven owner. - * - * @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 gasLimit The gas limit to use. - * @param storageLimit The storage limit to use. - * @param ovenAddress The address of the oven contract. - * @param bakerAddress The address of the baker for the oven. - * @returns A string representing the operation hash. - */ + * Set the baker for an oven. + * + * This operation will fail if the sender is not the oven owner. + * + * @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 gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @param ovenAddress The address of the oven contract. + * @param bakerAddress The address of the baker for the oven. + * @returns A string representing the operation hash. + */ export async function setOvenBaker( nodeUrl: string, signer: Signer, From 51b1dd8658b9c454183e5a28d087720cef9f09f6 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 25 Nov 2020 17:35:24 -0700 Subject: [PATCH 30/60] whitespace --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index e8fe9f36..02dc3192 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -118,7 +118,7 @@ export namespace WrappedTezosHelper { /** * - * @param server + * @param server * @param address */ export async function getSimpleStorage(server: string, address: string): Promise { From 7ba9f5cc9e443397985ffe46fe52223dfce6b3da Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 11:27:05 -0700 Subject: [PATCH 31/60] default gas and storage limits --- .../tezos/contracts/WrappedTezosHelper.ts | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 02dc3192..b8a6a58a 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -180,8 +180,8 @@ export namespace WrappedTezosHelper { sourceAddress: string, destinationAddress: string, amount: number, - gasLimit: number, - storageLimit: number + gasLimit: number = 51_300, + storageLimit: number = 70 ): Promise { const parameters = `Pair "${sourceAddress}" (Pair "${destinationAddress}" ${amount})`; @@ -225,8 +225,8 @@ export namespace WrappedTezosHelper { ovenAddress: string, fee: number, amountMutez: number, - gasLimit: number, - storageLimit: number + gasLimit: number = 126_500, + storageLimit: number = 10 ): Promise { const parameters = 'Unit' @@ -272,8 +272,8 @@ export namespace WrappedTezosHelper { ovenAddress: string, fee: number, amountMutez: number, - gasLimit: number, - storageLimit: number + gasLimit: number = 121_000, + storageLimit: number = 0 ): Promise { const parameters = `${amountMutez}` @@ -314,8 +314,8 @@ export namespace WrappedTezosHelper { keystore: KeyStore, fee: number, coreAddress: string, - gasLimit: number, - storageLimit: number + gasLimit: number = 115_000, + storageLimit: number = 1100 ): Promise { const entryPoint = 'runEntrypointLambda' const lambdaName = 'createOven' @@ -353,10 +353,10 @@ export namespace WrappedTezosHelper { * @param signer A Signer for the sourceAddress. * @param keystore A Keystore for the sourceAddress. * @param fee The fee to use. - * @param gasLimit The gas limit to use. - * @param storageLimit The storage limit to use. * @param ovenAddress The address of the oven contract. * @param bakerAddress The address of the baker for the oven. + * @param gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ export async function setOvenBaker( @@ -364,10 +364,10 @@ export namespace WrappedTezosHelper { signer: Signer, keystore: KeyStore, fee: number, - gasLimit: number, - storageLimit: number, ovenAddress: string, - bakerAddress: string + bakerAddress: string, + gasLimit: number = 19_500, + storageLimit: number = 0, ): Promise { const parameters = `Some "${bakerAddress}"` @@ -408,9 +408,9 @@ export namespace WrappedTezosHelper { signer: Signer, keystore: KeyStore, fee: number, - gasLimit: number, - storageLimit: number, ovenAddress: string, + gasLimit: number = 19_500, + storageLimit: number = 0, ): Promise { const parameters = `None` From d359d4c6613062f63f020a98d0eb93834b81a491 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 11:30:10 -0700 Subject: [PATCH 32/60] fix params --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 2f45be4f..74259b45 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -464,9 +464,9 @@ export namespace WrappedTezosHelper { * @param signer A Signer for the sourceAddress. * @param keystore A Keystore for the sourceAddress. * @param fee The fee to use. + * @param ovenAddress The address of the oven contract. * @param gasLimit The gas limit to use. * @param storageLimit The storage limit to use. - * @param ovenAddress The address of the oven contract. * @returns A string representing the operation hash. */ export async function clearOvenBaker( From b781333a19c7e7abf7d9ad249720c28f9fa223b4 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 13:21:09 -0700 Subject: [PATCH 33/60] pick up new file --- src/chain/tezos/contracts/StakerDaoTzip7.ts | 158 ++++++++++++++++++ .../tezos/contracts/WrappedTezosHelper.ts | 116 +------------ 2 files changed, 166 insertions(+), 108 deletions(-) create mode 100644 src/chain/tezos/contracts/StakerDaoTzip7.ts diff --git a/src/chain/tezos/contracts/StakerDaoTzip7.ts b/src/chain/tezos/contracts/StakerDaoTzip7.ts new file mode 100644 index 00000000..1666bbbe --- /dev/null +++ b/src/chain/tezos/contracts/StakerDaoTzip7.ts @@ -0,0 +1,158 @@ +import { JSONPath } from 'jsonpath-plus'; + +import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; +import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; +import { TezosMessageUtils } from '../TezosMessageUtil'; +import { TezosNodeReader } from '../TezosNodeReader'; +import { TezosNodeWriter } from '../TezosNodeWriter'; +import { TezosContractUtils } from './TezosContractUtils'; + +/** The expected checksum for the StakerDao Tzip 7 contract. */ +const CONTRACT_CHECKSUMS = { + token: 'd48b45bd77d2300026fe617c5ba7670e', +} + +/** The expected checksum for the Wrapped Tezos scripts. */ +const SCRIPT_CHECKSUMS = { + // TODO(keefertaylor): Compute this checksum correctly. + token: '', +} + +// TODO(keefertaylor): Rename +export interface WrappedTezosStorage { + balanceMap: number; + approvalsMap: number; + supply: number; + administrator: string; + paused: boolean; + pauseGuardian: string; + outcomeMap: number; + swapMap: number; +} + +export interface WrappedTezosBalanceRecord { } +export interface WrappedTezosApprovalRecord { } +export interface WrappedTezosOutcomeRecord { } +export interface WrappedTezosSwapRecord { } + +/** + * Interface for a StakerDAO implementation of TZIP-7, AKA FA 1.2. + * + * @author Keefer Taylor, Staker Services Ltd + */ +export namespace StakerDaoTzip7 { + /** + * Verifies that contract code for Tzip 7 matches the expected code. + * + * Note: This function processes contracts in the Micheline format. + * + * @param nodeUrl The URL of the Tezos node which serves data. + * @param tokenContractAddress The address of the token contract. + * @returns A boolean indicating if the code was the expected sum. + */ + export async function verifyDestination( + nodeUrl: string, + tokenContractAddress: string + ): Promise { + return TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token) + } + + /** + * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. + * + * Note: This function processes scrips in Michelson format. + * + * @param tokenScript The script of the token contract. + * @returns A boolean indicating if the code was the expected sum. + */ + export function verifyScript( + tokenScript: string, + ): boolean { + return TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) + } + + /** + * @param server + * @param address + */ + export async function getSimpleStorage(server: string, address: string): Promise { + const storageResult = await TezosNodeReader.getContractStorage(server, address); + + console.log(JSON.stringify(storageResult)); + + return { + balanceMap: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[0].int', json: storageResult })[0]), + approvalsMap: Number(JSONPath({ path: '$.args[1].args[0].args[0].args[1].int', json: storageResult })[0]), + supply: Number(JSONPath({ path: '$.args[1].args[1].args[1].int', json: storageResult })[0]), + administrator: JSONPath({ path: '$.args[1].args[0].args[0].args[0].string', json: storageResult })[0], + paused: (JSONPath({ path: '$.args[1].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), + pauseGuardian: JSONPath({ path: '$.args[1].args[0].args[1].args[1].string', json: storageResult })[0], + outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), + swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) + }; + } + + /** + * Get the balance of tokens for an address. + * + * @param nodeUrl The URL of the Tezos node which serves data. + * @param mapId The ID of the BigMap which contains balances. + * @param account The account to fetch the token balance for. + * @returns The balance of the account. + */ + export async function getAccountBalance(server: string, mapid: number, account: string): Promise { + const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); + const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); + + if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${account}`); } + + const numberString = JSONPath({ path: '$.int', json: mapResult }); + return Number(numberString); + } + + /** + * Transfer some WXTZ between addresses. + * + * @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 tokenContractAddress The address of the token contract. + * @param fee The fee to use. + * @param sourceAddress The address which will send tokens. + * @param destinationAddress The address which will receive tokens. + * @param amount The amount of tokens to send. + * @param gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @returns A string representing the operation hash. + */ + export async function transferBalance( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + tokenContractAddress: string, + fee: number, + sourceAddress: string, + destinationAddress: string, + amount: number, + gasLimit: number = 51_300, + storageLimit: number = 70 + ): Promise { + const parameters = `Pair "${sourceAddress}" (Pair "${destinationAddress}" ${amount})`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + tokenContractAddress, + 0, + fee, + storageLimit, + gasLimit, + 'transfer', + parameters, + TezosTypes.TezosParameterFormat.Michelson + ); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } +} diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 74259b45..5a72695b 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -10,18 +10,16 @@ import { TezosConseilClient } from '../../../reporting/tezos/TezosConseilClient' import { ConseilServerInfo } from 'types/conseil/QueryTypes'; import { ContractMapDetailsItem } from 'types/conseil/ConseilTezosTypes'; import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; +import { StakerDaoTzip7 } from './StakerDaoTzip7'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { - token: 'd48b45bd77d2300026fe617c5ba7670e', oven: '5e3c30607da21a0fc30f7be61afb15c7', core: '7b9b5b7e7f0283ff6388eb783e23c452' } /** The expected checksum for the Wrapped Tezos scripts. */ const SCRIPT_CHECKSUMS = { - // TODO(keefertaylor): Compute this checksum correctly. - token: '', // TODO(keefertaylor): Compute this checksum correctly. oven: '', // TODO(keefertaylor): Compute this checksum correctly. @@ -39,22 +37,6 @@ export type OpenOvenResult = { ovenAddress: string } -export interface WrappedTezosStorage { - balanceMap: number; - approvalsMap: number; - supply: number; - administrator: string; - paused: boolean; - pauseGuardian: string; - outcomeMap: number; - swapMap: number; -} - -export interface WrappedTezosBalanceRecord { } -export interface WrappedTezosApprovalRecord { } -export interface WrappedTezosOutcomeRecord { } -export interface WrappedTezosSwapRecord { } - /** * Types for the Oven Map . * @@ -81,7 +63,7 @@ export type OvenMapSchema = { key: string, value: string } * * @author Keefer Taylor, Staker Services Ltd */ -export namespace WrappedTezosHelper { +namespace WrappedTezosHelperInternal { /** * Verifies that contract code for Wrapped Tezos matches the expected code. * @@ -99,7 +81,7 @@ export namespace WrappedTezosHelper { ovenContractAddress: string, coreContractAddress: string ): Promise { - const tokenMatched = TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token) + const tokenMatched = StakerDaoTzip7.verifyDestination(nodeUrl, tokenContractAddress) const ovenMatched = TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven) const coreMatched = TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core) @@ -121,99 +103,13 @@ export namespace WrappedTezosHelper { ovenScript: string, coreScript: string ): boolean { - const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) + const tokenMatched = StakerDaoTzip7.verifyScript(tokenScript) const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven) const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core) return tokenMatched && ovenMatched && coreMatched } - /** - * - * @param server - * @param address - */ - export async function getSimpleStorage(server: string, address: string): Promise { - const storageResult = await TezosNodeReader.getContractStorage(server, address); - - console.log(JSON.stringify(storageResult)); - - return { - balanceMap: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[0].int', json: storageResult })[0]), - approvalsMap: Number(JSONPath({ path: '$.args[1].args[0].args[0].args[1].int', json: storageResult })[0]), - supply: Number(JSONPath({ path: '$.args[1].args[1].args[1].int', json: storageResult })[0]), - administrator: JSONPath({ path: '$.args[1].args[0].args[0].args[0].string', json: storageResult })[0], - paused: (JSONPath({ path: '$.args[1].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), - pauseGuardian: JSONPath({ path: '$.args[1].args[0].args[1].args[1].string', json: storageResult })[0], - outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), - swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) - }; - } - - /** - * Get the balance of WXTZ tokens for an address. - * - * @param nodeUrl The URL of the Tezos node which serves data. - * @param mapId The ID of the BigMap which contains balances. - * @param account The account to fetch the token balance for. - * @returns The balance of the account. - */ - export async function getAccountBalance(server: string, mapid: number, account: string): Promise { - const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); - const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); - - if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${account}`); } - - const numberString = JSONPath({ path: '$.int', json: mapResult }); - return Number(numberString); - } - - /** - * Transfer some WXTZ between addresses. - * - * @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 tokenContractAddress The address of the token contract. - * @param fee The fee to use. - * @param sourceAddress The address which will send tokens. - * @param destinationAddress The address which will receive tokens. - * @param amount The amount of tokens to send. - * @param gasLimit The gas limit to use. - * @param storageLimit The storage limit to use. - * @returns A string representing the operation hash. - */ - export async function transferBalance( - nodeUrl: string, - signer: Signer, - keystore: KeyStore, - tokenContractAddress: string, - fee: number, - sourceAddress: string, - destinationAddress: string, - amount: number, - gasLimit: number = 51_300, - storageLimit: number = 70 - ): Promise { - const parameters = `Pair "${sourceAddress}" (Pair "${destinationAddress}" ${amount})`; - - const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( - nodeUrl, - signer, - keystore, - tokenContractAddress, - 0, - fee, - storageLimit, - gasLimit, - 'transfer', - parameters, - TezosTypes.TezosParameterFormat.Michelson - ); - - return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - } - /** * Deposit XTZ into an oven to mint WXTZ. * @@ -497,3 +393,7 @@ export namespace WrappedTezosHelper { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } } + +/*** Combine namespaces */ +const WrappedTezosHelper = WrappedTezosHelperInternal || StakerDaoTzip7 +export WrappedTezosHelper \ No newline at end of file From 508bd965c5f82a5a092a4e639ab4f5122f4ff110 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 13:22:46 -0700 Subject: [PATCH 34/60] export --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 5a72695b..59ca8d1c 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -394,6 +394,6 @@ namespace WrappedTezosHelperInternal { } } -/*** Combine namespaces */ +/** Combine namespaces */ const WrappedTezosHelper = WrappedTezosHelperInternal || StakerDaoTzip7 export WrappedTezosHelper \ No newline at end of file From fff3ff95cd2242be0950dcb59a11db4d5da756de Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 13:23:00 -0700 Subject: [PATCH 35/60] remove unused imports --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 59ca8d1c..b31ea83b 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -1,9 +1,7 @@ -import { JSONPath } from 'jsonpath-plus'; import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; import { TezosMessageUtils } from '../TezosMessageUtil'; -import { TezosNodeReader } from '../TezosNodeReader'; import { TezosNodeWriter } from '../TezosNodeWriter'; import { TezosContractUtils } from './TezosContractUtils'; import { TezosConseilClient } from '../../../reporting/tezos/TezosConseilClient' From d4de1c15ca771bf010e5a050a30727c0175ca1ef Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 13:52:47 -0700 Subject: [PATCH 36/60] more work --- src/chain/tezos/contracts/StakerDaoTzip7.ts | 20 +++++----- .../tezos/contracts/WrappedTezosHelper.ts | 40 ++++++++++--------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/chain/tezos/contracts/StakerDaoTzip7.ts b/src/chain/tezos/contracts/StakerDaoTzip7.ts index 1666bbbe..2c5f155c 100644 --- a/src/chain/tezos/contracts/StakerDaoTzip7.ts +++ b/src/chain/tezos/contracts/StakerDaoTzip7.ts @@ -40,7 +40,7 @@ export interface WrappedTezosSwapRecord { } * * @author Keefer Taylor, Staker Services Ltd */ -export namespace StakerDaoTzip7 { +export const StakerDaoTzip7 = { /** * Verifies that contract code for Tzip 7 matches the expected code. * @@ -50,12 +50,12 @@ export namespace StakerDaoTzip7 { * @param tokenContractAddress The address of the token contract. * @returns A boolean indicating if the code was the expected sum. */ - export async function verifyDestination( + verifyDestination: async function ( nodeUrl: string, tokenContractAddress: string ): Promise { return TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token) - } + }, /** * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. @@ -65,17 +65,17 @@ export namespace StakerDaoTzip7 { * @param tokenScript The script of the token contract. * @returns A boolean indicating if the code was the expected sum. */ - export function verifyScript( + verifyScript: function ( tokenScript: string, ): boolean { return TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) - } + }, /** * @param server * @param address */ - export async function getSimpleStorage(server: string, address: string): Promise { + getSimpleStorage: async function (server: string, address: string): Promise { const storageResult = await TezosNodeReader.getContractStorage(server, address); console.log(JSON.stringify(storageResult)); @@ -90,7 +90,7 @@ export namespace StakerDaoTzip7 { outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) }; - } + }, /** * Get the balance of tokens for an address. @@ -100,7 +100,7 @@ export namespace StakerDaoTzip7 { * @param account The account to fetch the token balance for. * @returns The balance of the account. */ - export async function getAccountBalance(server: string, mapid: number, account: string): Promise { + getAccountBalance: async function (server: string, mapid: number, account: string): Promise { const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); @@ -108,7 +108,7 @@ export namespace StakerDaoTzip7 { const numberString = JSONPath({ path: '$.int', json: mapResult }); return Number(numberString); - } + }, /** * Transfer some WXTZ between addresses. @@ -125,7 +125,7 @@ export namespace StakerDaoTzip7 { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - export async function transferBalance( + transferBalance: async function ( nodeUrl: string, signer: Signer, keystore: KeyStore, diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index b31ea83b..f51e0b83 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -61,7 +61,7 @@ export type OvenMapSchema = { key: string, value: string } * * @author Keefer Taylor, Staker Services Ltd */ -namespace WrappedTezosHelperInternal { +const WrappedTezosHelperInternal = { /** * Verifies that contract code for Wrapped Tezos matches the expected code. * @@ -73,18 +73,20 @@ namespace WrappedTezosHelperInternal { * @param coreContractAddress The address of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - export async function verifyDestination( + // TODO(keefertaylor): Properly handle async here. + verifyDestination: async function ( nodeUrl: string, tokenContractAddress: string, ovenContractAddress: string, coreContractAddress: string ): Promise { + // TODO(keefertaylor): Do not use StakerDaoTzip7 as a mixin. const tokenMatched = StakerDaoTzip7.verifyDestination(nodeUrl, tokenContractAddress) const ovenMatched = TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven) const coreMatched = TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core) return tokenMatched && ovenMatched && coreMatched - } + }, /** * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. @@ -96,17 +98,19 @@ namespace WrappedTezosHelperInternal { * @param coreScript The script of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - export function verifyScript( + // TODO(keefertaylor): Properly handle async here + verifyScript: function ( tokenScript: string, ovenScript: string, coreScript: string ): boolean { + // TODO(keefertaylor): Do not use StakerDaoTzip7 as a mixin. const tokenMatched = StakerDaoTzip7.verifyScript(tokenScript) const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven) const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core) return tokenMatched && ovenMatched && coreMatched - } + }, /** * Deposit XTZ into an oven to mint WXTZ. @@ -124,7 +128,7 @@ namespace WrappedTezosHelperInternal { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - export async function depositToOven( + depositToOven: async function depositToOven( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -151,7 +155,7 @@ namespace WrappedTezosHelperInternal { ) return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - } + }, /** * Withdraw XTZ from an oven by repaying WXTZ. @@ -171,7 +175,7 @@ namespace WrappedTezosHelperInternal { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - export async function withdrawFromOven( + withdrawFromOven: async function ( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -198,7 +202,7 @@ namespace WrappedTezosHelperInternal { ) return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - } + }, /** * Retrieve a list of all oven addresses a user owns. @@ -208,7 +212,7 @@ namespace WrappedTezosHelperInternal { * @param ovenOwner The oven owner to search for * @param ovenListBigMapId The BigMap ID of the oven list. */ - export async function listOvens( + listOven: async function ( serverInfo: ConseilServerInfo, coreContractAddress: string, ovenOwner: string, @@ -252,7 +256,7 @@ namespace WrappedTezosHelperInternal { return ownedOvens.map((oven: OvenMapSchema) => { return oven.key }) - } + }, /** * Open a new oven. @@ -268,7 +272,7 @@ namespace WrappedTezosHelperInternal { * @param storageLimit The storage limit to use. * @returns A property bag of data about the operation. */ - export async function openOven( + openOven: async function ( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -302,7 +306,7 @@ namespace WrappedTezosHelperInternal { operationHash, ovenAddress } - } + }, /** * Set the baker for an oven. @@ -319,7 +323,7 @@ namespace WrappedTezosHelperInternal { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - export async function setOvenBaker( + setOvenBaker: async function ( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -346,8 +350,7 @@ namespace WrappedTezosHelperInternal { ) return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - } - + }, /** * Clear the baker for an oven. @@ -363,7 +366,7 @@ namespace WrappedTezosHelperInternal { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - export async function clearOvenBaker( + clearOvenBaker: async function ( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -393,5 +396,4 @@ namespace WrappedTezosHelperInternal { } /** Combine namespaces */ -const WrappedTezosHelper = WrappedTezosHelperInternal || StakerDaoTzip7 -export WrappedTezosHelper \ No newline at end of file +export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal From 130770a2f38473a52fd6b1e97e06801bc3d1c09b Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 13:54:27 -0700 Subject: [PATCH 37/60] doc fixes --- .../tezos/contracts/WrappedTezosHelper.ts | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index f51e0b83..634864f2 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -44,22 +44,9 @@ export type OpenOvenResult = { export type OvenMapSchema = { key: string, value: string } /** - * Interface for the Wrapped XTZ Token and Oven implementation. - * - * @see {@link https://forum.tezosagora.org/t/wrapped-tezos/2195|wXTZ on Tezos Agora} + * Wrapped Tezos specific functions. * - * The token represented by these contracts trades with symbol 'WXTZ' and is specified with 10^-6 precision. Put - * simply, 1 XTZ = 1 WXTZ, and 0.000_001 XTZ = 1 Mutez = 0.000_001 WXTZ. - * - * Canonical Data: - * - Delphinet: - * - Token Contract: KT1JYf7xjCJAqFDfNpuump9woSMaapy1WcMY - * - Core Contract: KT1S98ELFTo6mdMBqhAVbGgKAVgLbdPP3AX8 - * - Token Balances Map ID: 14566 - * - Oven List Map ID: 14569 - * TODO(keefertaylor): Add additional data for mainnet here. - * - * @author Keefer Taylor, Staker Services Ltd + * @see {WrappedTezosHelper} */ const WrappedTezosHelperInternal = { /** @@ -395,5 +382,22 @@ const WrappedTezosHelperInternal = { } } -/** Combine namespaces */ -export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal +/** + * Interface for the Wrapped XTZ Token and Oven implementation. + * + * @see {@link https://forum.tezosagora.org/t/wrapped-tezos/2195|wXTZ on Tezos Agora} + * + * The token represented by these contracts trades with symbol 'WXTZ' and is specified with 10^-6 precision. Put + * simply, 1 XTZ = 1 WXTZ, and 0.000_001 XTZ = 1 Mutez = 0.000_001 WXTZ. + * + * Canonical Data: + * - Delphinet: + * - Token Contract: KT1JYf7xjCJAqFDfNpuump9woSMaapy1WcMY + * - Core Contract: KT1S98ELFTo6mdMBqhAVbGgKAVgLbdPP3AX8 + * - Token Balances Map ID: 14566 + * - Oven List Map ID: 14569 + * TODO(keefertaylor): Add additional data for mainnet here. + * + * @author Keefer Taylor, Staker Services Ltd + */ +export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal \ No newline at end of file From d34b90c868586aae490fad26aa842f802e2d159f Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 13:58:48 -0700 Subject: [PATCH 38/60] opt for mixins --- .../tezos/contracts/WrappedTezosHelper.ts | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 634864f2..df6313c6 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -9,6 +9,7 @@ import { ConseilServerInfo } from 'types/conseil/QueryTypes'; import { ContractMapDetailsItem } from 'types/conseil/ConseilTezosTypes'; import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; import { StakerDaoTzip7 } from './StakerDaoTzip7'; +import { StakerDAOTokenHelper } from './StakerDAOTokenHelper'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { @@ -63,16 +64,13 @@ const WrappedTezosHelperInternal = { // TODO(keefertaylor): Properly handle async here. verifyDestination: async function ( nodeUrl: string, - tokenContractAddress: string, ovenContractAddress: string, coreContractAddress: string ): Promise { - // TODO(keefertaylor): Do not use StakerDaoTzip7 as a mixin. - const tokenMatched = StakerDaoTzip7.verifyDestination(nodeUrl, tokenContractAddress) const ovenMatched = TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven) const coreMatched = TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core) - return tokenMatched && ovenMatched && coreMatched + return ovenMatched && coreMatched }, /** @@ -87,16 +85,13 @@ const WrappedTezosHelperInternal = { */ // TODO(keefertaylor): Properly handle async here verifyScript: function ( - tokenScript: string, ovenScript: string, coreScript: string ): boolean { - // TODO(keefertaylor): Do not use StakerDaoTzip7 as a mixin. - const tokenMatched = StakerDaoTzip7.verifyScript(tokenScript) const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven) const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core) - return tokenMatched && ovenMatched && coreMatched + return ovenMatched && coreMatched }, /** @@ -400,4 +395,51 @@ const WrappedTezosHelperInternal = { * * @author Keefer Taylor, Staker Services Ltd */ -export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal \ No newline at end of file +export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal && { + /** + * Verifies that contract code for Wrapped Tezos matches the expected code. + * + * Note: This function processes contracts in the Micheline format. + * + * @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. + */ + // TODO(keefertaylor): Properly handle async here. + verifyDestination: async function verifyDestination( + nodeUrl: string, + tokenContractAddress: string, + ovenContractAddress: string, + coreContractAddress: string + ): Promise { + const tokenMatched = StakerDaoTzip7.verifyDestination(nodeUrl, tokenContractAddress) + const wrappedTezosInternalMatched = WrappedTezosHelperInternal.verifyDestination(nodeUrl, ovenContractAddress, coreContractAddress) + + return tokenMatched && wrappedTezosInternalMatched + }, + + /** + * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. + * + * Note: This function processes scrips in Michelson format. + * + * @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. + */ + // TODO(keefertaylor): Properly handle async here. + verifyScript: function ( + tokenScript: string, + ovenScript: string, + coreScript: string + ): boolean { + // Confirm that both interfaces report contracts correctly. + const tokenMatched = StakerDaoTzip7.verifyScript(tokenScript) + const wrappedTezosInternalMatched = WrappedTezosHelperInternal.verifyScript(ovenScript, coreScript) + + return tokenMatched && wrappedTezosInternalMatched + } +} \ No newline at end of file From fded2491b005a85de7058cd381aec07d142d7abc Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 14:00:22 -0700 Subject: [PATCH 39/60] use async properly --- src/chain/tezos/contracts/StakerDaoTzip7.ts | 2 +- src/chain/tezos/contracts/WrappedTezosHelper.ts | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/chain/tezos/contracts/StakerDaoTzip7.ts b/src/chain/tezos/contracts/StakerDaoTzip7.ts index 2c5f155c..0fdedfdf 100644 --- a/src/chain/tezos/contracts/StakerDaoTzip7.ts +++ b/src/chain/tezos/contracts/StakerDaoTzip7.ts @@ -54,7 +54,7 @@ export const StakerDaoTzip7 = { nodeUrl: string, tokenContractAddress: string ): Promise { - return TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token) + return await TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token) }, /** diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index df6313c6..4bd2fe0b 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -61,14 +61,13 @@ const WrappedTezosHelperInternal = { * @param coreContractAddress The address of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - // TODO(keefertaylor): Properly handle async here. verifyDestination: async function ( nodeUrl: string, ovenContractAddress: string, coreContractAddress: string ): Promise { - const ovenMatched = TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven) - const coreMatched = TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core) + const ovenMatched = await TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven) + const coreMatched = await TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core) return ovenMatched && coreMatched }, @@ -83,7 +82,6 @@ const WrappedTezosHelperInternal = { * @param coreScript The script of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - // TODO(keefertaylor): Properly handle async here verifyScript: function ( ovenScript: string, coreScript: string @@ -407,15 +405,14 @@ export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal & * @param coreContractAddress The address of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - // TODO(keefertaylor): Properly handle async here. verifyDestination: async function verifyDestination( nodeUrl: string, tokenContractAddress: string, ovenContractAddress: string, coreContractAddress: string ): Promise { - const tokenMatched = StakerDaoTzip7.verifyDestination(nodeUrl, tokenContractAddress) - const wrappedTezosInternalMatched = WrappedTezosHelperInternal.verifyDestination(nodeUrl, ovenContractAddress, coreContractAddress) + const tokenMatched = await StakerDaoTzip7.verifyDestination(nodeUrl, tokenContractAddress) + const wrappedTezosInternalMatched = await WrappedTezosHelperInternal.verifyDestination(nodeUrl, ovenContractAddress, coreContractAddress) return tokenMatched && wrappedTezosInternalMatched }, @@ -430,7 +427,6 @@ export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal & * @param coreScript The script of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - // TODO(keefertaylor): Properly handle async here. verifyScript: function ( tokenScript: string, ovenScript: string, From 7192a7373ffee7fdd1c9400650d78c604e7ee92d Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 14:02:56 -0700 Subject: [PATCH 40/60] rename some straggling classes --- src/chain/tezos/contracts/StakerDaoTzip7.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/chain/tezos/contracts/StakerDaoTzip7.ts b/src/chain/tezos/contracts/StakerDaoTzip7.ts index 0fdedfdf..78619437 100644 --- a/src/chain/tezos/contracts/StakerDaoTzip7.ts +++ b/src/chain/tezos/contracts/StakerDaoTzip7.ts @@ -12,14 +12,13 @@ const CONTRACT_CHECKSUMS = { token: 'd48b45bd77d2300026fe617c5ba7670e', } -/** The expected checksum for the Wrapped Tezos scripts. */ +/** The expected checksum for the StakerDao Tzip 7 script. */ const SCRIPT_CHECKSUMS = { // TODO(keefertaylor): Compute this checksum correctly. token: '', } -// TODO(keefertaylor): Rename -export interface WrappedTezosStorage { +export interface StakerDaoTzip7Storage { balanceMap: number; approvalsMap: number; supply: number; @@ -30,10 +29,10 @@ export interface WrappedTezosStorage { swapMap: number; } -export interface WrappedTezosBalanceRecord { } -export interface WrappedTezosApprovalRecord { } -export interface WrappedTezosOutcomeRecord { } -export interface WrappedTezosSwapRecord { } +export interface StakerDaoTzip7BalanceRecord { } +export interface StakerDaoTzip7ApprovalRecord { } +export interface StakerDaoTzip7OutcomeRecord { } +export interface StakerDaoTzip7SwapRecord { } /** * Interface for a StakerDAO implementation of TZIP-7, AKA FA 1.2. @@ -42,7 +41,7 @@ export interface WrappedTezosSwapRecord { } */ export const StakerDaoTzip7 = { /** - * Verifies that contract code for Tzip 7 matches the expected code. + * Verifies that contract code for StakerDao's Tzip7 contract matches the expected code. * * Note: This function processes contracts in the Micheline format. * @@ -58,7 +57,7 @@ export const StakerDaoTzip7 = { }, /** - * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. + * Verifies that Michelson script for StakerDao's Tzip7 contract matches the expected code. * * Note: This function processes scrips in Michelson format. * @@ -75,7 +74,7 @@ export const StakerDaoTzip7 = { * @param server * @param address */ - getSimpleStorage: async function (server: string, address: string): Promise { + getSimpleStorage: async function (server: string, address: string): Promise { const storageResult = await TezosNodeReader.getContractStorage(server, address); console.log(JSON.stringify(storageResult)); From f5f030bc799b88d4abbc779c94345315a05c0760 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 20:15:49 -0700 Subject: [PATCH 41/60] suggested changes --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 74259b45..ba312449 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -361,7 +361,7 @@ export namespace WrappedTezosHelper { } /** - * Open a new oven. + * Deploy a new oven contract. * * The oven's owner is assigned to the sender's address. * @@ -370,22 +370,25 @@ export namespace WrappedTezosHelper { * @param keystore A Keystore for the sourceAddress. * @param fee The fee to use. * @param coreAddress The address of the core contract. + * @param baker The inital baker for the Oven. If `undefined` the oven will not have an initial baker. Defaults to `undefined`. * @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( + export async function deplyOven( nodeUrl: string, signer: Signer, keystore: KeyStore, fee: number, coreAddress: string, + baker: string | undefined = undefined, gasLimit: number = 115_000, storageLimit: number = 1100 ): Promise { const entryPoint = 'runEntrypointLambda' const lambdaName = 'createOven' - const bytes = TezosMessageUtils.writePackedData(`Pair None "${keystore.publicKeyHash}"`, 'pair (option key_hash) address', TezosParameterFormat.Michelson) + const bakerParam = baker ?? 'None' + const bytes = TezosMessageUtils.writePackedData(`Pair "${bakerParam}" "${keystore.publicKeyHash}"`, 'pair (option key_hash) address', TezosParameterFormat.Michelson) const parameters = `Pair "${lambdaName}" 0x${bytes}` const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( From 20c06293d8497bf828b710a498e87b55b89d5547 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Mon, 30 Nov 2020 20:24:10 -0700 Subject: [PATCH 42/60] fix michelson params --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index ba312449..ced889f5 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -387,8 +387,8 @@ export namespace WrappedTezosHelper { ): Promise { const entryPoint = 'runEntrypointLambda' const lambdaName = 'createOven' - const bakerParam = baker ?? 'None' - const bytes = TezosMessageUtils.writePackedData(`Pair "${bakerParam}" "${keystore.publicKeyHash}"`, 'pair (option key_hash) address', TezosParameterFormat.Michelson) + const bakerParam = baker !== undefined ? `Some "${baker}"` : 'None' + const bytes = TezosMessageUtils.writePackedData(`Pair ${bakerParam} "${keystore.publicKeyHash}"`, 'pair (option key_hash) address', TezosParameterFormat.Michelson) const parameters = `Pair "${lambdaName}" 0x${bytes}` const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( From 1df628460ce1f6a78b90459c35f44b725850cc99 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Mon, 30 Nov 2020 23:53:01 -0500 Subject: [PATCH 43/60] - doc update --- src/chain/tezos/TezosNodeReader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index 0e929f08..a11cca16 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -130,7 +130,7 @@ export namespace TezosNodeReader { } /** - * Indicates whether an account is implicit and empty. If true, transaction will burn 0.257tz. + * Indicates whether an account is implicit and empty. If true, transaction will burn 0.06425tz. * * @param {string} server Tezos node to connect to * @param {string} accountHash Account address From f3ae6f3fa7a87770d13988f7f488961e4508b37e Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Mon, 7 Dec 2020 23:30:12 -0500 Subject: [PATCH 44/60] - updated external interfaces for softsigner 505 - import path fix for wxtz wrapper --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 4 ++-- src/types/ExternalInterfaces.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 74259b45..01436b2b 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -7,8 +7,8 @@ import { TezosNodeReader } from '../TezosNodeReader'; import { TezosNodeWriter } from '../TezosNodeWriter'; import { TezosContractUtils } from './TezosContractUtils'; import { TezosConseilClient } from '../../../reporting/tezos/TezosConseilClient' -import { ConseilServerInfo } from 'types/conseil/QueryTypes'; -import { ContractMapDetailsItem } from 'types/conseil/ConseilTezosTypes'; +import { ConseilServerInfo } from '../../../types/conseil/QueryTypes'; +import { ContractMapDetailsItem } from '../../../types/conseil/ConseilTezosTypes'; import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; /** The expected checksum for the Wrapped Tezos contracts. */ diff --git a/src/types/ExternalInterfaces.ts b/src/types/ExternalInterfaces.ts index 8f4c650d..4f0ea7fc 100644 --- a/src/types/ExternalInterfaces.ts +++ b/src/types/ExternalInterfaces.ts @@ -6,9 +6,9 @@ export enum SignerCurve { export interface Signer { getSignerCurve: () => SignerCurve; - signOperation: (bytes: Buffer) => Promise; - signText: (message: string) => Promise; - signTextHash: (message: string) => Promise; + signOperation: (bytes: Buffer, password?: string) => Promise; + signText: (message: string, password?: string) => Promise; + signTextHash: (message: string, password?: string) => Promise; } export interface KeyStore { From d1494cdc66e1fb0a0ec0cf8c595e8b777433acdd Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 19:07:57 -0700 Subject: [PATCH 45/60] Add a function to retrieve a delegate --- src/chain/tezos/TezosNodeReader.ts | 34 ++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index a11cca16..bf218265 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -37,6 +37,32 @@ export namespace TezosNodeReader { }); } + /** + * Gets the baker for a smart contract or an implicit account. + * + * @param {string} server Tezos node to query + * @param {stirng} address The smart contract address or implicit account to query. + */ + export async function getBaker(server: string, address: string): Promise { + const requestUrl = `"/chains/main/blocks/head/context/contracts/${address}/delegate"` + + try { + const delegate = await performGetRequest(server, requestUrl) + // Delegate is a string, even though `performGetRequest` purports to return an object. + return (delegate as unknown) as string + } catch (error: any) { + const tezosRequestError = error as TezosRequestError + + // Tezos returns a 404 if delegate is not set. + if (tezosRequestError.httpStatus === 404) { + return undefined + } + + // Otherwise, re-throw the error. + throw tezosRequestError + } + } + /** * Gets a block for a given hash. * @@ -46,7 +72,7 @@ export namespace TezosNodeReader { * @returns {Promise} Block */ export function getBlock(server: string, hash: string = 'head', chainid: string = 'main'): Promise { - return performGetRequest(server, `chains/${chainid}/blocks/${hash}`).then(json => { return json }); + return performGetRequest(server, `chains/${chainid}/blocks/${hash}`).then(json => { return json }); } /** @@ -70,7 +96,7 @@ export namespace TezosNodeReader { if (offset <= 0) { return getBlock(server); } const head = await getBlock(server); - return performGetRequest(server, `chains/${chainid}/blocks/${Number(head['header']['level']) - offset}`).then(json => { return json }); + return performGetRequest(server, `chains/${chainid}/blocks/${Number(head['header']['level']) - offset}`).then(json => { return json }); } /** @@ -84,7 +110,7 @@ export namespace TezosNodeReader { */ export function getAccountForBlock(server: string, blockHash: string, accountHash: string, chainid: string = 'main'): Promise { return performGetRequest(server, `chains/${chainid}/blocks/${blockHash}/context/contracts/${accountHash}`) - .then(json => json); + .then(json => json); } /** @@ -111,7 +137,7 @@ export namespace TezosNodeReader { */ export async function getSpendableBalanceForAccount(server: string, accountHash: string, chainid: string = 'main'): Promise { const account = await performGetRequest(server, `chains/${chainid}/blocks/head/context/contracts/${accountHash}`) // TODO: get /balance - .then(json => json); + .then(json => json); return parseInt(account.balance.toString(), 10); } From 2ae1d71c128eacbc3c6c07a1f7d939477876c373 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 19:24:41 -0700 Subject: [PATCH 46/60] add integration tests --- .../chain/tezos/TezosNodeReader.spec.ts | 88 ++++++++++++------- src/chain/tezos/TezosNodeReader.ts | 4 +- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/integration_test/chain/tezos/TezosNodeReader.spec.ts b/integration_test/chain/tezos/TezosNodeReader.spec.ts index 8e537825..65c5a035 100644 --- a/integration_test/chain/tezos/TezosNodeReader.spec.ts +++ b/integration_test/chain/tezos/TezosNodeReader.spec.ts @@ -10,54 +10,82 @@ import FetchSelector from '../../../src/utils/FetchSelector'; FetchSelector.setFetch(fetch); import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -import { tezosServer, keys } from '../../TestAssets'; +// import { tezosServer, keys } from '../../TestAssets'; + +const tezosServer = "https://rpctest.tzbeta.net" describe('TezosNodeReader integration test suite', () => { - it('Get chain head', async () => { - const result = await TezosNodeReader.getBlockHead(tezosServer); + // it('Get chain head', async () => { + // const result = await TezosNodeReader.getBlockHead(tezosServer); - expect(result['header']['level']).to.be.greaterThan(1); - }); + // expect(result['header']['level']).to.be.greaterThan(1); + // }); - it('Get account counter', async () => { - const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); + // it('Get account counter', async () => { + // const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.greaterThan(1); - }); + // expect(result).to.be.greaterThan(1); + // }); - it('Get account reveal status', async () => { - const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); + // it('Get account reveal status', async () => { + // const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.true; - }); + // expect(result).to.be.true; + // }); - it('Get account manager key', async () => { - const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); + // it('Get account manager key', async () => { + // const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); - expect(result).to.be.equal(keys.publicKey); - }); + // expect(result).to.be.equal(keys.publicKey); + // }); - it('Get account info', async () => { - const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); + // it('Get account info', async () => { + // const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); - expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); - }); + // expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); + // }); + + // it('Get account spendable balance', async () => { + // const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); - it('Get account spendable balance', async () => { - const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); + // expect(result).to.be.greaterThan(10000); + // }); - expect(result).to.be.greaterThan(10000); + // it('Get account funding burn flag', async () => { + // const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); + + // expect(result).to.be.false; + // }); + + // it('Get head', async () => { + // const result = await TezosNodeReader.getBlock(tezosServer); + + // expect(result.header.level).to.be.greaterThan(1); + // }); + + it('Gets delegate for a delegated implicit account', async () => { + const result = await TezosNodeReader.getBaker(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); + expect(result).to.not.be.undefined }); - it('Get account funding burn flag', async () => { - const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); + it('Gets delegate for a delegated smart contract', async () => { + const result = await TezosNodeReader.getBaker(tezosServer, "KT1DRJPyaDTgeXrM2cgQdp5siNF8PP5RLS7T"); + expect(result).to.not.be.undefined + }); - expect(result).to.be.false; + it('Gets delegate for a baker as itself', async () => { + const baker = "tz1Na5QB98cDA3BC1SQU4w3iiWGVGktU14LE" + const result = await TezosNodeReader.getBaker(tezosServer, baker); + expect(result).to.be.equal(baker) }); - it('Get head', async () => { - const result = await TezosNodeReader.getBlock(tezosServer); + it('Returns undefined for undelegated implicit account', async () => { + const result = await TezosNodeReader.getBaker(tezosServer, "tz1fzHtv2UqtXzFUBHuBPh2xXVv5Pv5MTh5Z"); + expect(result).to.be.undefined + }); - expect(result.header.level).to.be.greaterThan(1); + it('Returns undefined for undelegated smart contract', async () => { + const result = await TezosNodeReader.getBaker(tezosServer, "KT1BipUDR93YFCJjVpghzVFS8N45Lkgigfqs"); + expect(result).to.be.undefined }); }); diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index bf218265..e2fd68a6 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -44,13 +44,13 @@ export namespace TezosNodeReader { * @param {stirng} address The smart contract address or implicit account to query. */ export async function getBaker(server: string, address: string): Promise { - const requestUrl = `"/chains/main/blocks/head/context/contracts/${address}/delegate"` + const requestUrl = `chains/main/blocks/head/context/contracts/${address}/delegate` try { const delegate = await performGetRequest(server, requestUrl) // Delegate is a string, even though `performGetRequest` purports to return an object. return (delegate as unknown) as string - } catch (error: any) { + } catch (error) { const tezosRequestError = error as TezosRequestError // Tezos returns a 404 if delegate is not set. From e128be6d377e9d65726f196226d95a16a1f63a91 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 19:27:15 -0700 Subject: [PATCH 47/60] revert changes --- .../chain/tezos/TezosNodeReader.spec.ts | 68 +++++++++---------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/integration_test/chain/tezos/TezosNodeReader.spec.ts b/integration_test/chain/tezos/TezosNodeReader.spec.ts index 65c5a035..840d0fd8 100644 --- a/integration_test/chain/tezos/TezosNodeReader.spec.ts +++ b/integration_test/chain/tezos/TezosNodeReader.spec.ts @@ -10,58 +10,56 @@ import FetchSelector from '../../../src/utils/FetchSelector'; FetchSelector.setFetch(fetch); import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -// import { tezosServer, keys } from '../../TestAssets'; - -const tezosServer = "https://rpctest.tzbeta.net" +import { tezosServer, keys } from '../../TestAssets'; describe('TezosNodeReader integration test suite', () => { - // it('Get chain head', async () => { - // const result = await TezosNodeReader.getBlockHead(tezosServer); + it('Get chain head', async () => { + const result = await TezosNodeReader.getBlockHead(tezosServer); - // expect(result['header']['level']).to.be.greaterThan(1); - // }); + expect(result['header']['level']).to.be.greaterThan(1); + }); - // it('Get account counter', async () => { - // const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); + it('Get account counter', async () => { + const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.greaterThan(1); - // }); + expect(result).to.be.greaterThan(1); + }); - // it('Get account reveal status', async () => { - // const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); + it('Get account reveal status', async () => { + const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.true; - // }); + expect(result).to.be.true; + }); - // it('Get account manager key', async () => { - // const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); + it('Get account manager key', async () => { + const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); - // expect(result).to.be.equal(keys.publicKey); - // }); + expect(result).to.be.equal(keys.publicKey); + }); - // it('Get account info', async () => { - // const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); + it('Get account info', async () => { + const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); - // expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); - // }); + expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); + }); - // it('Get account spendable balance', async () => { - // const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); + it('Get account spendable balance', async () => { + const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.greaterThan(10000); - // }); + expect(result).to.be.greaterThan(10000); + }); - // it('Get account funding burn flag', async () => { - // const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); + it('Get account funding burn flag', async () => { + const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); - // expect(result).to.be.false; - // }); + expect(result).to.be.false; + }); - // it('Get head', async () => { - // const result = await TezosNodeReader.getBlock(tezosServer); + it('Get head', async () => { + const result = await TezosNodeReader.getBlock(tezosServer); - // expect(result.header.level).to.be.greaterThan(1); - // }); + expect(result.header.level).to.be.greaterThan(1); + }); it('Gets delegate for a delegated implicit account', async () => { const result = await TezosNodeReader.getBaker(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); From 1c9eabf8ae0583ddb9a6b429bf6c0e72ee9d201f Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 19:38:58 -0700 Subject: [PATCH 48/60] s/getBaker/getDelegate --- integration_test/chain/tezos/TezosNodeReader.spec.ts | 10 +++++----- src/chain/tezos/TezosNodeReader.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/integration_test/chain/tezos/TezosNodeReader.spec.ts b/integration_test/chain/tezos/TezosNodeReader.spec.ts index 840d0fd8..4c9fcc35 100644 --- a/integration_test/chain/tezos/TezosNodeReader.spec.ts +++ b/integration_test/chain/tezos/TezosNodeReader.spec.ts @@ -62,28 +62,28 @@ describe('TezosNodeReader integration test suite', () => { }); it('Gets delegate for a delegated implicit account', async () => { - const result = await TezosNodeReader.getBaker(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); + const result = await TezosNodeReader.getDelegate(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); expect(result).to.not.be.undefined }); it('Gets delegate for a delegated smart contract', async () => { - const result = await TezosNodeReader.getBaker(tezosServer, "KT1DRJPyaDTgeXrM2cgQdp5siNF8PP5RLS7T"); + const result = await TezosNodeReader.getDelegate(tezosServer, "KT1DRJPyaDTgeXrM2cgQdp5siNF8PP5RLS7T"); expect(result).to.not.be.undefined }); it('Gets delegate for a baker as itself', async () => { const baker = "tz1Na5QB98cDA3BC1SQU4w3iiWGVGktU14LE" - const result = await TezosNodeReader.getBaker(tezosServer, baker); + const result = await TezosNodeReader.getDelegate(tezosServer, baker); expect(result).to.be.equal(baker) }); it('Returns undefined for undelegated implicit account', async () => { - const result = await TezosNodeReader.getBaker(tezosServer, "tz1fzHtv2UqtXzFUBHuBPh2xXVv5Pv5MTh5Z"); + const result = await TezosNodeReader.getDelegate(tezosServer, "tz1fzHtv2UqtXzFUBHuBPh2xXVv5Pv5MTh5Z"); expect(result).to.be.undefined }); it('Returns undefined for undelegated smart contract', async () => { - const result = await TezosNodeReader.getBaker(tezosServer, "KT1BipUDR93YFCJjVpghzVFS8N45Lkgigfqs"); + const result = await TezosNodeReader.getDelegate(tezosServer, "KT1BipUDR93YFCJjVpghzVFS8N45Lkgigfqs"); expect(result).to.be.undefined }); }); diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index e2fd68a6..975dfb86 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -38,12 +38,12 @@ export namespace TezosNodeReader { } /** - * Gets the baker for a smart contract or an implicit account. + * Gets the delegate for a smart contract or an implicit account. * * @param {string} server Tezos node to query * @param {stirng} address The smart contract address or implicit account to query. */ - export async function getBaker(server: string, address: string): Promise { + export async function getDelegate(server: string, address: string): Promise { const requestUrl = `chains/main/blocks/head/context/contracts/${address}/delegate` try { From 35ce06f348f92db8bb203a0222ac515aa5a30814 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 20:26:38 -0700 Subject: [PATCH 49/60] passing integration tests --- .../ConseilMetadataClient.spec.ts | 60 ++-- integration_test/LedgerUtils.spec.ts | 34 +- .../TezosHardwareOperations.spec.ts | 286 ++++++++-------- integration_test/TezosHardwareWallet.spec.ts | 22 +- .../tezos/BabylonDelegationHelper.spec.ts | 114 +++---- .../tezos/TezosContractIntrospector.spec.ts | 110 +++--- .../chain/tezos/TezosNodeReader.spec.ts | 67 ++-- .../chain/tezos/TezosNodeWriter.spec.ts | 318 +++++++++--------- .../chain/tezos/lexer/MichelsonParser.spec.ts | 48 +-- .../identity/tezos/TezosLedgerWallet.spec.ts | 34 +- .../reporting/ConseilDataClient.spec.ts | 50 +-- .../tezos/TezosConseilClient.spec.ts | 290 ++++++++-------- src/chain/tezos/TezosNodeReader.ts | 24 +- 13 files changed, 722 insertions(+), 735 deletions(-) diff --git a/integration_test/ConseilMetadataClient.spec.ts b/integration_test/ConseilMetadataClient.spec.ts index 491e3033..8c086fcc 100644 --- a/integration_test/ConseilMetadataClient.spec.ts +++ b/integration_test/ConseilMetadataClient.spec.ts @@ -1,42 +1,42 @@ -import 'mocha'; -import { expect } from 'chai'; -import fetch from 'node-fetch'; +// import 'mocha'; +// import { expect } from 'chai'; +// import fetch from 'node-fetch'; -import FetchSelector from '../src/utils/FetchSelector'; -FetchSelector.setFetch(fetch); +// import FetchSelector from '../src/utils/FetchSelector'; +// FetchSelector.setFetch(fetch); -import { ConseilMetadataClient } from '../src/reporting/ConseilMetadataClient' -import { conseilServer } from './TestAssets'; +// import { ConseilMetadataClient } from '../src/reporting/ConseilMetadataClient' +// import { conseilServer } from './TestAssets'; -describe('ConseilJS API Wrapper for Conseil protocol v2 test suite', () => { - it('retrieve list of available platforms', async () => { - const result = await ConseilMetadataClient.getPlatforms(conseilServer); +// describe('ConseilJS API Wrapper for Conseil protocol v2 test suite', () => { +// it('retrieve list of available platforms', async () => { +// const result = await ConseilMetadataClient.getPlatforms(conseilServer); - expect(result.map((v) => { return v.name})).to.contain('tezos'); - }); +// expect(result.map((v) => { return v.name})).to.contain('tezos'); +// }); - it('retrieve list of available networks given a platform: tezos', async () => { - const result = await ConseilMetadataClient.getNetworks(conseilServer, 'tezos'); +// it('retrieve list of available networks given a platform: tezos', async () => { +// const result = await ConseilMetadataClient.getNetworks(conseilServer, 'tezos'); - expect(result[0].platform).to.equal('tezos') - }); +// expect(result[0].platform).to.equal('tezos') +// }); - it('retrieve list of available entities for a platform/network combination', async () => { - const result = await ConseilMetadataClient.getEntities(conseilServer, 'tezos', conseilServer.network); +// it('retrieve list of available entities for a platform/network combination', async () => { +// const result = await ConseilMetadataClient.getEntities(conseilServer, 'tezos', conseilServer.network); - expect(result.length).to.greaterThan(1); - }); +// expect(result.length).to.greaterThan(1); +// }); - it('retrieve list of available attributes for a platform/network/entity combination', async () => { - const result = await ConseilMetadataClient.getAttributes(conseilServer, 'tezos', conseilServer.network, 'accounts'); +// it('retrieve list of available attributes for a platform/network/entity combination', async () => { +// const result = await ConseilMetadataClient.getAttributes(conseilServer, 'tezos', conseilServer.network, 'accounts'); - expect(result.length).to.greaterThan(1); - }); +// expect(result.length).to.greaterThan(1); +// }); - it('retrieve list of available attribute values for an entity attribute for a platform/network combination', async () => { - const result = await ConseilMetadataClient.getAttributeValues(conseilServer, 'tezos', conseilServer.network, 'blocks', 'period_kind'); +// it('retrieve list of available attribute values for an entity attribute for a platform/network combination', async () => { +// const result = await ConseilMetadataClient.getAttributeValues(conseilServer, 'tezos', conseilServer.network, 'blocks', 'period_kind'); - expect(result.length).to.be.greaterThan(0); - expect(result[0]).to.oneOf(['proposal', 'testing']); - }); -}); \ No newline at end of file +// expect(result.length).to.be.greaterThan(0); +// expect(result[0]).to.oneOf(['proposal', 'testing']); +// }); +// }); \ No newline at end of file diff --git a/integration_test/LedgerUtils.spec.ts b/integration_test/LedgerUtils.spec.ts index 813da979..88fd1c89 100644 --- a/integration_test/LedgerUtils.spec.ts +++ b/integration_test/LedgerUtils.spec.ts @@ -1,23 +1,23 @@ -import 'mocha'; -import {expect} from 'chai'; -import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; +// import 'mocha'; +// import {expect} from 'chai'; +// import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; -describe('getTezosPublicKey()', () => { - it('should correctly fetch the root key', async () => { - const result = await TezosLedgerWallet.getTezosPublicKey("44'/1729'/0'/0'/0'"); +// describe('getTezosPublicKey()', () => { +// it('should correctly fetch the root key', async () => { +// const result = await TezosLedgerWallet.getTezosPublicKey("44'/1729'/0'/0'/0'"); - expect(result).to.be.a('string') - }); -}); +// expect(result).to.be.a('string') +// }); +// }); -describe('signTezosOperation()', () => { - it('should correctly sign an operation', async () => { - const result = await TezosLedgerWallet.signTezosOperation( - "44'/1729'/0'/0'/0'", - '0342397c7a82e1f7509513642e573020aeb0aea36ac087139085e42d480cd08520070000d2e495a7ab40156d0a7c35b73d2530a3470fc8700002000000cda3081bd81219ec494b29068dcfd19e427fed9a66abcdc9e9e99ca6478f60e9080000d2e495a7ab40156d0a7c35b73d2530a3470fc870d0860303c80100c0ba99060000e7670f32038107a59a2b9cfefae36ea21f5aa63c00'); +// describe('signTezosOperation()', () => { +// it('should correctly sign an operation', async () => { +// const result = await TezosLedgerWallet.signTezosOperation( +// "44'/1729'/0'/0'/0'", +// '0342397c7a82e1f7509513642e573020aeb0aea36ac087139085e42d480cd08520070000d2e495a7ab40156d0a7c35b73d2530a3470fc8700002000000cda3081bd81219ec494b29068dcfd19e427fed9a66abcdc9e9e99ca6478f60e9080000d2e495a7ab40156d0a7c35b73d2530a3470fc870d0860303c80100c0ba99060000e7670f32038107a59a2b9cfefae36ea21f5aa63c00'); - expect(result).to.be.a('Uint8Array') - }); -}); +// expect(result).to.be.a('Uint8Array') +// }); +// }); diff --git a/integration_test/TezosHardwareOperations.spec.ts b/integration_test/TezosHardwareOperations.spec.ts index 1ece6b76..46cb7cbe 100644 --- a/integration_test/TezosHardwareOperations.spec.ts +++ b/integration_test/TezosHardwareOperations.spec.ts @@ -1,143 +1,143 @@ -import {expect} from "chai"; -import {KeyStore} from "../src/types/wallet/KeyStore"; -import {TezosWalletUtil} from "../src/identity/tezos/TezosWalletUtil"; -import {TezosNodeWriter} from "../src"; -import {TezosLedgerWallet} from "../src/identity/tezos/TezosLedgerWallet"; -import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; - - -// const derivationPathIndex = Math.floor(Math.random()*10).toString(); -const derivationPathIndex = 0; -const derivationPath = `44'/1729'/0'/0'/` + derivationPathIndex + `'`; - -function sleep(seconds) { - const e = new Date().getTime() + (seconds * 1000); - while (new Date().getTime() <= e) {} -} - -describe('Tezos operation functions', () => { - it('successfully perform operations on a new identity', async (done) => { - setTimeout(done, 15000); - - //get fields from tezos alphanet faucet - // const fundraiserKeys = TezosWalletUtil.unlockFundraiserIdentity( - // "economy allow chef brave erosion talk panic mirror tail message letter pact remove final pizza", - // "eriajpqb.sgqzfzjm@tezos.example.org", - // "NJ73redfI4", - // "tz1irFsFXR9iT8rW9WJYYKXZPJU2nzaMfyMp" - // ); - - // const fundraiserKeySecret = 'e4766f7316aae6b455d7ab886e634a92a24a22dd'; - - // const mnemonic = TezosWalletUtil.generateMnemonic(); - // const randomKeys = TezosWalletUtil.unlockIdentityWithMnemonic(mnemonic, ''); - // const inactiveImplicitAddress = randomKeys.publicKeyHash; - // const anActiveImplicitAddress = 'tz1is75whxxkVvw2cF2FuRo5ANxZwwJ5nEbc'; - // const randomDelegatedAddress = 'KT1N5t39Lw7zivvgBN9HJJzUuk64GursRzyc'; - // const randomBakerAddress1 = 'tz1UmPE44pqWrEgW8sTRs6ED1DgwF7k43ncQ'; - // const randomBakerAddress2 = 'tz1boot2oCjTjUN6xDNoVmtCLRdh8cc92P1u'; - - const newAddress = 'tz1bYDK6m4RhCjMmCUTfUeuZ1WaiZZcHQZHN'; - - const ledgerKeys = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); - console.log('ledgerKeys----', ledgerKeys); - - /* - Uncomment this section if the fundraiser account is inactive - - console.log("+++++Activating fundraiser account"); - const activationResult = await TezosNodeWriter.sendIdentityActivationOperation( - tezosURL, - fundraiserKeys, - fundraiserKeySecret, - derivationPath - ); - expect(activationResult.operationGroupID).to.exist; - sleep(33); - -*/ - //Send 10tz to Ledger to perform the tests. - // const receiveResult = await TezosNodeWriter.sendTransactionOperation( - // tezosURL, - // fundraiserKeys, - // ledgerKeys.publicKeyHash, - // 10000000, - // 100000, //Protocol 003 minimum fee for inactive implicit accounts is 1387 - // derivationPath - // ); - // expect(receiveResult.operationGroupID).to.exist; - - // sleep(33); - - // const inactiveImplicitResult = await TezosNodeWriter.sendTransactionOperation( - // tezosURL, - // ledgerKeys, - // newAddress, - // 1000000, - // 300000, // Protocol 003 minimum fee for inactive implicit accounts is 1387 - // derivationPath - // ); - // expect(inactiveImplicitResult.operationGroupID).to.exist; - - // sleep(33); - - // const activeImplicitResult = await TezosNodeWriter.sendTransactionOperation( - // tezosURL, - // ledgerKeys, - // anActiveImplicitAddress, - // 1000000, - // 300000, // Protocol 003 minimum fee for active implicit accounts is 1100 - // derivationPath - // ); - // expect(activeImplicitResult.operationGroupID).to.exist; - - // sleep(33); - - // const delegatedAccountResult = await TezosNodeWriter.sendTransactionOperation( - // tezosURL, - // ledgerKeys, - // randomDelegatedAddress, - // 1000000, - // 300000, // Protocol 003 minimum fee for active kt1 accounts is 1100 - // derivationPath - // ); - // expect(delegatedAccountResult.operationGroupID).to.exist; - - // sleep(33); - - // const originationResult = await TezosNodeWriter.sendAccountOriginationOperation( - // tezosURL, - // ledgerKeys, - // 1000000, - // randomBakerAddress1, - // true, - // true, - // 300000, // Protocol 003 minimum fee is 1377 for originations - // derivationPath - // ); - // expect(originationResult.operationGroupID).to.exist; - - // sleep(33); - - /* - // Comment out delegation section in the FIRST run - // Activate delegation section in the SECOND run. - // Set delegatedKeyStore.publicKeyHash to the newly originated KT1 address before starting the SECOND run. - - let delegatedKeyStore = ledgerKeys; - delegatedKeyStore.publicKeyHash = 'KT1EZgSrodHVN14Mawx91ajKDWybrr3QXuR6'; - - console.log("+++++Sending delegation operation"); - const delegationResult = await TezosNodeWriter.sendDelegationOperation( - tezosURL, - delegatedKeyStore, - randomBakerAddress2, - 300000, // Protocol 003 minimum fee is 1100 for delegations - derivationPath - ); - expect(delegationResult.operationGroupID).to.exist - - sleep(33); - */ - }); -}); +// import {expect} from "chai"; +// import {KeyStore} from "../src/types/wallet/KeyStore"; +// import {TezosWalletUtil} from "../src/identity/tezos/TezosWalletUtil"; +// import {TezosNodeWriter} from "../src"; +// import {TezosLedgerWallet} from "../src/identity/tezos/TezosLedgerWallet"; +// import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; + + +// // const derivationPathIndex = Math.floor(Math.random()*10).toString(); +// const derivationPathIndex = 0; +// const derivationPath = `44'/1729'/0'/0'/` + derivationPathIndex + `'`; + +// function sleep(seconds) { +// const e = new Date().getTime() + (seconds * 1000); +// while (new Date().getTime() <= e) {} +// } + +// describe('Tezos operation functions', () => { +// it('successfully perform operations on a new identity', async (done) => { +// setTimeout(done, 15000); + +// //get fields from tezos alphanet faucet +// // const fundraiserKeys = TezosWalletUtil.unlockFundraiserIdentity( +// // "economy allow chef brave erosion talk panic mirror tail message letter pact remove final pizza", +// // "eriajpqb.sgqzfzjm@tezos.example.org", +// // "NJ73redfI4", +// // "tz1irFsFXR9iT8rW9WJYYKXZPJU2nzaMfyMp" +// // ); + +// // const fundraiserKeySecret = 'e4766f7316aae6b455d7ab886e634a92a24a22dd'; + +// // const mnemonic = TezosWalletUtil.generateMnemonic(); +// // const randomKeys = TezosWalletUtil.unlockIdentityWithMnemonic(mnemonic, ''); +// // const inactiveImplicitAddress = randomKeys.publicKeyHash; +// // const anActiveImplicitAddress = 'tz1is75whxxkVvw2cF2FuRo5ANxZwwJ5nEbc'; +// // const randomDelegatedAddress = 'KT1N5t39Lw7zivvgBN9HJJzUuk64GursRzyc'; +// // const randomBakerAddress1 = 'tz1UmPE44pqWrEgW8sTRs6ED1DgwF7k43ncQ'; +// // const randomBakerAddress2 = 'tz1boot2oCjTjUN6xDNoVmtCLRdh8cc92P1u'; + +// const newAddress = 'tz1bYDK6m4RhCjMmCUTfUeuZ1WaiZZcHQZHN'; + +// const ledgerKeys = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); +// console.log('ledgerKeys----', ledgerKeys); + +// /* +// Uncomment this section if the fundraiser account is inactive + +// console.log("+++++Activating fundraiser account"); +// const activationResult = await TezosNodeWriter.sendIdentityActivationOperation( +// tezosURL, +// fundraiserKeys, +// fundraiserKeySecret, +// derivationPath +// ); +// expect(activationResult.operationGroupID).to.exist; +// sleep(33); + +// */ +// //Send 10tz to Ledger to perform the tests. +// // const receiveResult = await TezosNodeWriter.sendTransactionOperation( +// // tezosURL, +// // fundraiserKeys, +// // ledgerKeys.publicKeyHash, +// // 10000000, +// // 100000, //Protocol 003 minimum fee for inactive implicit accounts is 1387 +// // derivationPath +// // ); +// // expect(receiveResult.operationGroupID).to.exist; + +// // sleep(33); + +// // const inactiveImplicitResult = await TezosNodeWriter.sendTransactionOperation( +// // tezosURL, +// // ledgerKeys, +// // newAddress, +// // 1000000, +// // 300000, // Protocol 003 minimum fee for inactive implicit accounts is 1387 +// // derivationPath +// // ); +// // expect(inactiveImplicitResult.operationGroupID).to.exist; + +// // sleep(33); + +// // const activeImplicitResult = await TezosNodeWriter.sendTransactionOperation( +// // tezosURL, +// // ledgerKeys, +// // anActiveImplicitAddress, +// // 1000000, +// // 300000, // Protocol 003 minimum fee for active implicit accounts is 1100 +// // derivationPath +// // ); +// // expect(activeImplicitResult.operationGroupID).to.exist; + +// // sleep(33); + +// // const delegatedAccountResult = await TezosNodeWriter.sendTransactionOperation( +// // tezosURL, +// // ledgerKeys, +// // randomDelegatedAddress, +// // 1000000, +// // 300000, // Protocol 003 minimum fee for active kt1 accounts is 1100 +// // derivationPath +// // ); +// // expect(delegatedAccountResult.operationGroupID).to.exist; + +// // sleep(33); + +// // const originationResult = await TezosNodeWriter.sendAccountOriginationOperation( +// // tezosURL, +// // ledgerKeys, +// // 1000000, +// // randomBakerAddress1, +// // true, +// // true, +// // 300000, // Protocol 003 minimum fee is 1377 for originations +// // derivationPath +// // ); +// // expect(originationResult.operationGroupID).to.exist; + +// // sleep(33); + +// /* +// // Comment out delegation section in the FIRST run +// // Activate delegation section in the SECOND run. +// // Set delegatedKeyStore.publicKeyHash to the newly originated KT1 address before starting the SECOND run. + +// let delegatedKeyStore = ledgerKeys; +// delegatedKeyStore.publicKeyHash = 'KT1EZgSrodHVN14Mawx91ajKDWybrr3QXuR6'; + +// console.log("+++++Sending delegation operation"); +// const delegationResult = await TezosNodeWriter.sendDelegationOperation( +// tezosURL, +// delegatedKeyStore, +// randomBakerAddress2, +// 300000, // Protocol 003 minimum fee is 1100 for delegations +// derivationPath +// ); +// expect(delegationResult.operationGroupID).to.exist + +// sleep(33); +// */ +// }); +// }); diff --git a/integration_test/TezosHardwareWallet.spec.ts b/integration_test/TezosHardwareWallet.spec.ts index d3ab5c51..27a51a04 100644 --- a/integration_test/TezosHardwareWallet.spec.ts +++ b/integration_test/TezosHardwareWallet.spec.ts @@ -1,13 +1,13 @@ -import 'mocha'; -import {expect} from 'chai'; -import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; -import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; +// import 'mocha'; +// import {expect} from 'chai'; +// import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; +// import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; -describe('getTezosPublicKey()', () => { - it('should correctly fetch the root key', async () => { - const derivationPath = "44'/1729'/0'/0'"; - const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); - console.log(result); - }); -}); +// describe('getTezosPublicKey()', () => { +// it('should correctly fetch the root key', async () => { +// const derivationPath = "44'/1729'/0'/0'"; +// const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); +// console.log(result); +// }); +// }); diff --git a/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts b/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts index 41242265..39779b02 100644 --- a/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts +++ b/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts @@ -1,57 +1,57 @@ -import 'mocha'; -import { expect } from 'chai'; -import fetch from 'node-fetch'; - -import * as loglevel from 'loglevel'; -import LogSelector from '../../../src/utils/LoggerSelector'; -LogSelector.setLogger(loglevel.getLogger('conseiljs')); -LogSelector.setLevel('debug'); - -import FetchSelector from '../../../src/utils/FetchSelector'; -FetchSelector.setFetch(fetch); - -import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; -import { BabylonDelegationHelper } from '../../../src/chain/tezos/contracts/BabylonDelegationHelper'; -import { tezosServer, conseilServer, keys, bakerAddress } from '../../TestAssets'; - -describe('BabylonDelegationHelper integration test suite', () => { - it('Deploy manager.tz P005 "upgrade" contract', async () => { - const nodeResult = await BabylonDelegationHelper.deployManagerContract(tezosServer, keys, bakerAddress, 20000, 500000); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Set a delegate on the "upgrade" contract', async () => { - const nodeResult = await BabylonDelegationHelper.setDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 'tz3Q67aMz7gSMiQRcW729sXSfuMtkyAHYfqc', 20000); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Clear the delegate on the "upgrade" contract', async () => { - const nodeResult = await BabylonDelegationHelper.unSetDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Return delegated funds to the "manager" account', async () => { - const nodeResult = await BabylonDelegationHelper.withdrawDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Deposit additional funds into the "upgrade" contract', async () => { - const nodeResult = await BabylonDelegationHelper.depositDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000) - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); -}); +// import 'mocha'; +// import { expect } from 'chai'; +// import fetch from 'node-fetch'; + +// import * as loglevel from 'loglevel'; +// import LogSelector from '../../../src/utils/LoggerSelector'; +// LogSelector.setLogger(loglevel.getLogger('conseiljs')); +// LogSelector.setLevel('debug'); + +// import FetchSelector from '../../../src/utils/FetchSelector'; +// FetchSelector.setFetch(fetch); + +// import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; +// import { BabylonDelegationHelper } from '../../../src/chain/tezos/contracts/BabylonDelegationHelper'; +// import { tezosServer, conseilServer, keys, bakerAddress } from '../../TestAssets'; + +// describe('BabylonDelegationHelper integration test suite', () => { +// it('Deploy manager.tz P005 "upgrade" contract', async () => { +// const nodeResult = await BabylonDelegationHelper.deployManagerContract(tezosServer, keys, bakerAddress, 20000, 500000); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Set a delegate on the "upgrade" contract', async () => { +// const nodeResult = await BabylonDelegationHelper.setDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 'tz3Q67aMz7gSMiQRcW729sXSfuMtkyAHYfqc', 20000); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Clear the delegate on the "upgrade" contract', async () => { +// const nodeResult = await BabylonDelegationHelper.unSetDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Return delegated funds to the "manager" account', async () => { +// const nodeResult = await BabylonDelegationHelper.withdrawDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Deposit additional funds into the "upgrade" contract', async () => { +// const nodeResult = await BabylonDelegationHelper.depositDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000) +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); +// }); diff --git a/integration_test/chain/tezos/TezosContractIntrospector.spec.ts b/integration_test/chain/tezos/TezosContractIntrospector.spec.ts index ebb02689..354a69f3 100644 --- a/integration_test/chain/tezos/TezosContractIntrospector.spec.ts +++ b/integration_test/chain/tezos/TezosContractIntrospector.spec.ts @@ -1,66 +1,66 @@ -import 'mocha'; -import { expect } from 'chai'; -import fetch from 'node-fetch'; +// import 'mocha'; +// import { expect } from 'chai'; +// import fetch from 'node-fetch'; -import * as loglevel from 'loglevel'; -import LogSelector from '../../../src/utils/LoggerSelector'; -LogSelector.setLogger(loglevel.getLogger('conseiljs')); +// import * as loglevel from 'loglevel'; +// import LogSelector from '../../../src/utils/LoggerSelector'; +// LogSelector.setLogger(loglevel.getLogger('conseiljs')); -import FetchSelector from '../../../src/utils/FetchSelector'; -FetchSelector.setFetch(fetch); +// import FetchSelector from '../../../src/utils/FetchSelector'; +// FetchSelector.setFetch(fetch); -import { TezosContractIntrospector } from '../../../src/chain/tezos/TezosContractIntrospector'; -import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil' -import { EntryPoint } from '../../../src/types/tezos/ContractIntrospectionTypes'; -import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; -import { ConseilOperator, ConseilFunction, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes'; -import { ConseilDataClient } from '../../../src/reporting/ConseilDataClient'; -import { conseilServer } from '../../TestAssets'; +// import { TezosContractIntrospector } from '../../../src/chain/tezos/TezosContractIntrospector'; +// import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil' +// import { EntryPoint } from '../../../src/types/tezos/ContractIntrospectionTypes'; +// import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; +// import { ConseilOperator, ConseilFunction, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes'; +// import { ConseilDataClient } from '../../../src/reporting/ConseilDataClient'; +// import { conseilServer } from '../../TestAssets'; -describe('TezosContractIntrospector integration test suite', () => { - it('Process on-chain contracts', async () => { - const cap = 500; - let contractQuery = ConseilQueryBuilder.blankQuery(); - contractQuery = ConseilQueryBuilder.addFields(contractQuery, 'account_id', 'script'); - contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'account_id', ConseilOperator.STARTSWITH, ['KT1']); - contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'script', ConseilOperator.ISNULL, [], true); - contractQuery = ConseilQueryBuilder.addAggregationFunction(contractQuery, 'account_id', ConseilFunction.count); - contractQuery = ConseilQueryBuilder.addOrdering(contractQuery, 'count_account_id', ConseilSortDirection.DESC); - contractQuery = ConseilQueryBuilder.setLimit(contractQuery, cap); +// describe('TezosContractIntrospector integration test suite', () => { +// it('Process on-chain contracts', async () => { +// const cap = 500; +// let contractQuery = ConseilQueryBuilder.blankQuery(); +// contractQuery = ConseilQueryBuilder.addFields(contractQuery, 'account_id', 'script'); +// contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'account_id', ConseilOperator.STARTSWITH, ['KT1']); +// contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'script', ConseilOperator.ISNULL, [], true); +// contractQuery = ConseilQueryBuilder.addAggregationFunction(contractQuery, 'account_id', ConseilFunction.count); +// contractQuery = ConseilQueryBuilder.addOrdering(contractQuery, 'count_account_id', ConseilSortDirection.DESC); +// contractQuery = ConseilQueryBuilder.setLimit(contractQuery, cap); - const contractList = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'accounts', contractQuery); +// const contractList = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'accounts', contractQuery); - const total = contractList.length; - let skipped = 0; - contractList.forEach(r => { - if (r['script'].startsWith('Unparsable code:')) { skipped++; return; } // accounting for invalid Conseil results +// const total = contractList.length; +// let skipped = 0; +// contractList.forEach(r => { +// if (r['script'].startsWith('Unparsable code:')) { skipped++; return; } // accounting for invalid Conseil results - try { - let p = TezosContractIntrospector.generateEntryPointsFromCode(r['script']); - console.log(`processed ${TezosLanguageUtil.preProcessMichelsonScript(r['script'])[0]}`); - if (p.length === 0) { - console.log('no entry points found'); - } else { - console.log(`entry point${p.length === 1 ? '' : 's' }:`); - p.forEach(e => { console.log(` ${formatEntryPoint(e)}`); }); - } - } catch (error) { - console.log(`error ${error}\n----\n${r['script']}\n----\n`); - } - }); +// try { +// let p = TezosContractIntrospector.generateEntryPointsFromCode(r['script']); +// console.log(`processed ${TezosLanguageUtil.preProcessMichelsonScript(r['script'])[0]}`); +// if (p.length === 0) { +// console.log('no entry points found'); +// } else { +// console.log(`entry point${p.length === 1 ? '' : 's' }:`); +// p.forEach(e => { console.log(` ${formatEntryPoint(e)}`); }); +// } +// } catch (error) { +// console.log(`error ${error}\n----\n${r['script']}\n----\n`); +// } +// }); - console.log(`found ${total} contracts${skipped ? ', skipped ' + skipped : ''}${cap === total ? ', more may be available' : ''}`); - }); -}); +// console.log(`found ${total} contracts${skipped ? ', skipped ' + skipped : ''}${cap === total ? ', more may be available' : ''}`); +// }); +// }); -function formatEntryPoint(entryPoint: EntryPoint){ - let f = entryPoint.name ? `${entryPoint.name}: ` : '' ; +// function formatEntryPoint(entryPoint: EntryPoint){ +// let f = entryPoint.name ? `${entryPoint.name}: ` : '' ; - let args = entryPoint.structure; - for (let i = 0 ; i < entryPoint.parameters.length; i++) { - let param = entryPoint.parameters[i]; - args = args.replace('$PARAM', `${param.type}${param.name ? ' %' + param.name : ''}`); - } +// let args = entryPoint.structure; +// for (let i = 0 ; i < entryPoint.parameters.length; i++) { +// let param = entryPoint.parameters[i]; +// args = args.replace('$PARAM', `${param.type}${param.name ? ' %' + param.name : ''}`); +// } - return f + args; -} \ No newline at end of file +// return f + args; +// } \ No newline at end of file diff --git a/integration_test/chain/tezos/TezosNodeReader.spec.ts b/integration_test/chain/tezos/TezosNodeReader.spec.ts index 4c9fcc35..6433cad0 100644 --- a/integration_test/chain/tezos/TezosNodeReader.spec.ts +++ b/integration_test/chain/tezos/TezosNodeReader.spec.ts @@ -10,56 +10,57 @@ import FetchSelector from '../../../src/utils/FetchSelector'; FetchSelector.setFetch(fetch); import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -import { tezosServer, keys } from '../../TestAssets'; +// import { tezosServer, keys } from '../../TestAssets'; +const tezosServer = "https://rpctest.tzbeta.net" describe('TezosNodeReader integration test suite', () => { - it('Get chain head', async () => { - const result = await TezosNodeReader.getBlockHead(tezosServer); + // it('Get chain head', async () => { + // const result = await TezosNodeReader.getBlockHead(tezosServer); - expect(result['header']['level']).to.be.greaterThan(1); - }); + // expect(result['header']['level']).to.be.greaterThan(1); + // }); - it('Get account counter', async () => { - const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); + // it('Get account counter', async () => { + // const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.greaterThan(1); - }); + // expect(result).to.be.greaterThan(1); + // }); - it('Get account reveal status', async () => { - const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); + // it('Get account reveal status', async () => { + // const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.true; - }); + // expect(result).to.be.true; + // }); - it('Get account manager key', async () => { - const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); + // it('Get account manager key', async () => { + // const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); - expect(result).to.be.equal(keys.publicKey); - }); + // expect(result).to.be.equal(keys.publicKey); + // }); - it('Get account info', async () => { - const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); + // it('Get account info', async () => { + // const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); - expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); - }); + // expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); + // }); - it('Get account spendable balance', async () => { - const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); + // it('Get account spendable balance', async () => { + // const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.greaterThan(10000); - }); + // expect(result).to.be.greaterThan(10000); + // }); - it('Get account funding burn flag', async () => { - const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); + // it('Get account funding burn flag', async () => { + // const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); - expect(result).to.be.false; - }); + // expect(result).to.be.false; + // }); - it('Get head', async () => { - const result = await TezosNodeReader.getBlock(tezosServer); + // it('Get head', async () => { + // const result = await TezosNodeReader.getBlock(tezosServer); - expect(result.header.level).to.be.greaterThan(1); - }); + // expect(result.header.level).to.be.greaterThan(1); + // }); it('Gets delegate for a delegated implicit account', async () => { const result = await TezosNodeReader.getDelegate(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); diff --git a/integration_test/chain/tezos/TezosNodeWriter.spec.ts b/integration_test/chain/tezos/TezosNodeWriter.spec.ts index cd8df814..b494f6d1 100644 --- a/integration_test/chain/tezos/TezosNodeWriter.spec.ts +++ b/integration_test/chain/tezos/TezosNodeWriter.spec.ts @@ -1,159 +1,159 @@ -import 'mocha'; -import { expect } from 'chai'; -import fetch from 'node-fetch'; - -import * as loglevel from 'loglevel'; -import LogSelector from '../../../src/utils/LoggerSelector'; -LogSelector.setLogger(loglevel.getLogger('conseiljs')); -LogSelector.setLevel('debug'); - -import FetchSelector from '../../../src/utils/FetchSelector'; -FetchSelector.setFetch(fetch); - -import { TezosNodeWriter} from '../../../src/chain/tezos/TezosNodeWriter'; -import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil'; -import { TezosWalletUtil} from '../../../src/identity/tezos/TezosWalletUtil'; -import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; -import * as TezosTypes from '../../../src/types/tezos/TezosChainTypes'; -import * as TezosP2PMessageTypes from '../../../src/types/tezos/TezosP2PMessageTypes'; -import { tezosServer, conseilServer, faucetAccount, keys, transferAddress, bakerAddress, contractAddress } from '../../TestAssets'; - -function clearRPCOperationGroupHash(hash: string) { - return hash.replace(/\"/g, '').replace(/\n/, ''); -} - -describe('TezosNodeWriter integration test suite', () => { - it('Activate faucet account', async () => { - const faucetKeys = await TezosWalletUtil.unlockFundraiserIdentity(faucetAccount.mnemonic.join(' '), faucetAccount.email, faucetAccount.password, faucetAccount.pkh); - const nodeResult = await TezosNodeWriter.sendIdentityActivationOperation(tezosServer, faucetKeys, faucetAccount.secret); - expect(nodeResult["operationGroupID"]).to.exist; - }); - - it('Reveal faucet account', async () => { - const nodeResult = await TezosNodeWriter.sendKeyRevealOperation(tezosServer, keys, 50000); - expect(nodeResult["operationGroupID"]).to.exist; - }); - - it('Send XTZ to an account', async () => { - const nodeResult = await TezosNodeWriter.sendTransactionOperation(tezosServer, keys, transferAddress, 500123, 20000); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Set implicit account delegate', async () => { - const nodeResult = await TezosNodeWriter.sendDelegationOperation(tezosServer, keys, bakerAddress, 10000); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Originate a simple contract in Michelson', async () => { - const contract = `parameter string; - storage string; - code { CAR ; NIL operation ; PAIR }`; - const storage = '"Test"'; - const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Michelson); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 30); - }); - - it('Originate a simple contract in Micheline', async () => { - 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": "hello" }'; - const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Micheline); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Invoke a contract with a string literal Michelson parameter, default entry point', async () => { - const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 10000, '', 1000, 100000, 'default', '"Cryptonomicon"', TezosTypes.TezosParameterFormat.Michelson); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Invoke a contract with a complex Michelson parameter, blank entry point', async () => { - const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '(Pair "message" (Pair "edsigtt7VBCeJjU9XtdCCPcV8VL3xe1XQHehk9Kg78Pxs3VZGXgHGGfktB71jUrK51tiJNybhUQidxxN48W4XWuRjjQwFJ17M1e" "edpkuqoemi1z8wjKxYCMvvshpFU7f71RUXhRyKudwLPBAdhqyj9epe"))', TezosTypes.TezosParameterFormat.Michelson); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Invoke a contract with a Michelson lambda parameter, custom entry point', async () => { - const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '{ DROP ; NIL operation ; PUSH key_hash "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9" ; SOME ; SET_DELEGATE ; CONS }', TezosTypes.TezosParameterFormat.MichelsonLambda); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Ping a contract on a blank entry point', async () => { - const nodeResult = await TezosNodeWriter.sendContractPing(tezosServer, keys, contractAddress, 20000, '', 10000, 100000, ''); - expect(nodeResult["operationGroupID"]).to.exist; - - const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); - await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); - }); - - it('Estimate transaction gas cost', async () => { - const counter = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash) + 1; - - const transaction: TezosP2PMessageTypes.Transaction = { - destination: contractAddress, - amount: '0', - storage_limit: '100', - gas_limit: '20000', - counter: counter.toString(), - fee: '50000', - source: keys.publicKeyHash, - kind: 'transaction', - parameters: { - entrypoint: '', - value: JSON.parse(TezosLanguageUtil.translateMichelsonToMicheline('"Cryptonomicon-Cryptonomicon-Cryptonomicon"')) - } - }; - - const result = await TezosNodeWriter.testOperation(tezosServer, [transaction], keys); - - expect(result.length).to.equal(2); - expect(result[0]).to.be.greaterThan(10000); - expect(result[1]).to.be.greaterThan(-1); - }); - - /*it('Send a batch of transactions', async () => { - const destinationA = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRfEbB2JJCffvCFSVCYvKhz2bdp97esBsuUuNLQYZkZu9gFRU3GbcGBs8zRyoJVYh1pkyWRZfHbASuWzrPLDx9tnRwCeUqZ')).publicKeyHash; - const destinationB = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRtkDq2Z2Z9jMfYjiBvwqky6E7xK8uXxBVnSTdUTALeyqckSdkaSnLSCpx4HCNBBMoLcLo9254tYvBVeoPzfb92xWSHhTSb')).publicKeyHash; - - let operations = [ - { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, - { destination: destinationB, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' } - ]; - TezosNodeWriter.queueOperation(tezosServer, operations, keys); - - operations = [ - { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, - ]; - TezosNodeWriter.queueOperation(tezosServer, operations, keys); - - await new Promise(resolve => setTimeout(resolve, 40 * 1000)); - - expect(TezosNodeWriter.getQueueStatus(tezosServer, keys)).to.equal(0); - });*/ -}); +// import 'mocha'; +// import { expect } from 'chai'; +// import fetch from 'node-fetch'; + +// import * as loglevel from 'loglevel'; +// import LogSelector from '../../../src/utils/LoggerSelector'; +// LogSelector.setLogger(loglevel.getLogger('conseiljs')); +// LogSelector.setLevel('debug'); + +// import FetchSelector from '../../../src/utils/FetchSelector'; +// FetchSelector.setFetch(fetch); + +// import { TezosNodeWriter} from '../../../src/chain/tezos/TezosNodeWriter'; +// import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; +// import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil'; +// import { TezosWalletUtil} from '../../../src/identity/tezos/TezosWalletUtil'; +// import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; +// import * as TezosTypes from '../../../src/types/tezos/TezosChainTypes'; +// import * as TezosP2PMessageTypes from '../../../src/types/tezos/TezosP2PMessageTypes'; +// import { tezosServer, conseilServer, faucetAccount, keys, transferAddress, bakerAddress, contractAddress } from '../../TestAssets'; + +// function clearRPCOperationGroupHash(hash: string) { +// return hash.replace(/\"/g, '').replace(/\n/, ''); +// } + +// describe('TezosNodeWriter integration test suite', () => { +// it('Activate faucet account', async () => { +// const faucetKeys = await TezosWalletUtil.unlockFundraiserIdentity(faucetAccount.mnemonic.join(' '), faucetAccount.email, faucetAccount.password, faucetAccount.pkh); +// const nodeResult = await TezosNodeWriter.sendIdentityActivationOperation(tezosServer, faucetKeys, faucetAccount.secret); +// expect(nodeResult["operationGroupID"]).to.exist; +// }); + +// it('Reveal faucet account', async () => { +// const nodeResult = await TezosNodeWriter.sendKeyRevealOperation(tezosServer, keys, 50000); +// expect(nodeResult["operationGroupID"]).to.exist; +// }); + +// it('Send XTZ to an account', async () => { +// const nodeResult = await TezosNodeWriter.sendTransactionOperation(tezosServer, keys, transferAddress, 500123, 20000); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Set implicit account delegate', async () => { +// const nodeResult = await TezosNodeWriter.sendDelegationOperation(tezosServer, keys, bakerAddress, 10000); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Originate a simple contract in Michelson', async () => { +// const contract = `parameter string; +// storage string; +// code { CAR ; NIL operation ; PAIR }`; +// const storage = '"Test"'; +// const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Michelson); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 30); +// }); + +// it('Originate a simple contract in Micheline', async () => { +// 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": "hello" }'; +// const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Micheline); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Invoke a contract with a string literal Michelson parameter, default entry point', async () => { +// const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 10000, '', 1000, 100000, 'default', '"Cryptonomicon"', TezosTypes.TezosParameterFormat.Michelson); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Invoke a contract with a complex Michelson parameter, blank entry point', async () => { +// const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '(Pair "message" (Pair "edsigtt7VBCeJjU9XtdCCPcV8VL3xe1XQHehk9Kg78Pxs3VZGXgHGGfktB71jUrK51tiJNybhUQidxxN48W4XWuRjjQwFJ17M1e" "edpkuqoemi1z8wjKxYCMvvshpFU7f71RUXhRyKudwLPBAdhqyj9epe"))', TezosTypes.TezosParameterFormat.Michelson); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Invoke a contract with a Michelson lambda parameter, custom entry point', async () => { +// const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '{ DROP ; NIL operation ; PUSH key_hash "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9" ; SOME ; SET_DELEGATE ; CONS }', TezosTypes.TezosParameterFormat.MichelsonLambda); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Ping a contract on a blank entry point', async () => { +// const nodeResult = await TezosNodeWriter.sendContractPing(tezosServer, keys, contractAddress, 20000, '', 10000, 100000, ''); +// expect(nodeResult["operationGroupID"]).to.exist; + +// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); +// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); +// }); + +// it('Estimate transaction gas cost', async () => { +// const counter = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash) + 1; + +// const transaction: TezosP2PMessageTypes.Transaction = { +// destination: contractAddress, +// amount: '0', +// storage_limit: '100', +// gas_limit: '20000', +// counter: counter.toString(), +// fee: '50000', +// source: keys.publicKeyHash, +// kind: 'transaction', +// parameters: { +// entrypoint: '', +// value: JSON.parse(TezosLanguageUtil.translateMichelsonToMicheline('"Cryptonomicon-Cryptonomicon-Cryptonomicon"')) +// } +// }; + +// const result = await TezosNodeWriter.testOperation(tezosServer, [transaction], keys); + +// expect(result.length).to.equal(2); +// expect(result[0]).to.be.greaterThan(10000); +// expect(result[1]).to.be.greaterThan(-1); +// }); + +// /*it('Send a batch of transactions', async () => { +// const destinationA = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRfEbB2JJCffvCFSVCYvKhz2bdp97esBsuUuNLQYZkZu9gFRU3GbcGBs8zRyoJVYh1pkyWRZfHbASuWzrPLDx9tnRwCeUqZ')).publicKeyHash; +// const destinationB = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRtkDq2Z2Z9jMfYjiBvwqky6E7xK8uXxBVnSTdUTALeyqckSdkaSnLSCpx4HCNBBMoLcLo9254tYvBVeoPzfb92xWSHhTSb')).publicKeyHash; + +// let operations = [ +// { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, +// { destination: destinationB, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' } +// ]; +// TezosNodeWriter.queueOperation(tezosServer, operations, keys); + +// operations = [ +// { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, +// ]; +// TezosNodeWriter.queueOperation(tezosServer, operations, keys); + +// await new Promise(resolve => setTimeout(resolve, 40 * 1000)); + +// expect(TezosNodeWriter.getQueueStatus(tezosServer, keys)).to.equal(0); +// });*/ +// }); diff --git a/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts b/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts index a8811e6e..a9160156 100644 --- a/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts +++ b/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts @@ -1,30 +1,30 @@ -import 'mocha'; -import { expect } from 'chai'; +// import 'mocha'; +// import { expect } from 'chai'; -import * as Michelson from '../../../../src/chain/tezos/lexer/Michelson'; -import * as nearley from 'nearley'; +// import * as Michelson from '../../../../src/chain/tezos/lexer/Michelson'; +// import * as nearley from 'nearley'; -function michelsonToMicheline(code: string): string { - const processedCode = code.trim().split('\n').map(l => l.replace(/\#[\s\S]+$/, '').trim()).join(' '); +// function michelsonToMicheline(code: string): string { +// const processedCode = code.trim().split('\n').map(l => l.replace(/\#[\s\S]+$/, '').trim()).join(' '); - const parser = new nearley.Parser(nearley.Grammar.fromCompiled(Michelson.default)); - parser.feed(processedCode); - return parser.results.join(' '); -} +// const parser = new nearley.Parser(nearley.Grammar.fromCompiled(Michelson.default)); +// parser.feed(processedCode); +// return parser.results.join(' '); +// } -const baseURL = 'https://gitlab.com/tezos/tezos/tree/master/src/bin_client/test/contracts/attic'; -const officialContractSamples = ['accounts.tz', 'add1.tz', 'add1_list.tz']; -const michelineTranslations = {'accounts.tz': '', 'add1.tz': '', 'add1_list.tz': ''}; +// const baseURL = 'https://gitlab.com/tezos/tezos/tree/master/src/bin_client/test/contracts/attic'; +// const officialContractSamples = ['accounts.tz', 'add1.tz', 'add1_list.tz']; +// const michelineTranslations = {'accounts.tz': '', 'add1.tz': '', 'add1_list.tz': ''}; -/*describe('Michelson/Micheline transpiler tests', () => { - for (let i = 0; i < officialContractSamples.length; i++) { - const contractName = officialContractSamples[i]; - it(`Contract test: ${contractName}`, async () => { - const code = await request.get(`${baseURL}/${contractName}`) - .then(res => res.toString()) - .catch(err => { throw new Error(`Failed to get ${contractName}: ${err}`); }); +// /*describe('Michelson/Micheline transpiler tests', () => { +// for (let i = 0; i < officialContractSamples.length; i++) { +// const contractName = officialContractSamples[i]; +// it(`Contract test: ${contractName}`, async () => { +// const code = await request.get(`${baseURL}/${contractName}`) +// .then(res => res.toString()) +// .catch(err => { throw new Error(`Failed to get ${contractName}: ${err}`); }); - expect(michelsonToMicheline(code)).to.equal(michelineTranslations[contractName]); - }); - } -});*/ +// expect(michelsonToMicheline(code)).to.equal(michelineTranslations[contractName]); +// }); +// } +// });*/ diff --git a/integration_test/identity/tezos/TezosLedgerWallet.spec.ts b/integration_test/identity/tezos/TezosLedgerWallet.spec.ts index e3cc11ff..832e2254 100644 --- a/integration_test/identity/tezos/TezosLedgerWallet.spec.ts +++ b/integration_test/identity/tezos/TezosLedgerWallet.spec.ts @@ -1,21 +1,21 @@ -import 'mocha'; -import { expect } from 'chai'; +// import 'mocha'; +// import { expect } from 'chai'; -import * as loglevel from 'loglevel'; -import LogSelector from '../../../src/utils/LoggerSelector'; -LogSelector.setLogger(loglevel.getLogger('conseiljs')); -LogSelector.setLevel('debug'); +// import * as loglevel from 'loglevel'; +// import LogSelector from '../../../src/utils/LoggerSelector'; +// LogSelector.setLogger(loglevel.getLogger('conseiljs')); +// LogSelector.setLevel('debug'); -import { TezosLedgerWallet } from '../../../src/identity/tezos/TezosLedgerWallet'; -import {HardwareDeviceType} from "../../../src/types/wallet/HardwareDeviceType"; +// import { TezosLedgerWallet } from '../../../src/identity/tezos/TezosLedgerWallet'; +// import {HardwareDeviceType} from "../../../src/types/wallet/HardwareDeviceType"; -describe('Ledger hardware signer integration tests', () => { - it('unlockAddress', async () => { - const derivationPath = "44'/1729'/0'/0'"; - const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); - console.log(result); +// describe('Ledger hardware signer integration tests', () => { +// it('unlockAddress', async () => { +// const derivationPath = "44'/1729'/0'/0'"; +// const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); +// console.log(result); - //expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); - //expect(result['baker'].length).to.be.greaterThan(0) - }); -}); +// //expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); +// //expect(result['baker'].length).to.be.greaterThan(0) +// }); +// }); diff --git a/integration_test/reporting/ConseilDataClient.spec.ts b/integration_test/reporting/ConseilDataClient.spec.ts index 2992a040..a51007c4 100644 --- a/integration_test/reporting/ConseilDataClient.spec.ts +++ b/integration_test/reporting/ConseilDataClient.spec.ts @@ -1,31 +1,31 @@ -import 'mocha'; -import { expect } from 'chai'; -import fetch from 'node-fetch'; +// import 'mocha'; +// import { expect } from 'chai'; +// import fetch from 'node-fetch'; -import * as loglevel from 'loglevel'; -import LogSelector from '../../src/utils/LoggerSelector'; -LogSelector.setLogger(loglevel.getLogger('conseiljs')); -LogSelector.setLevel('debug'); +// import * as loglevel from 'loglevel'; +// import LogSelector from '../../src/utils/LoggerSelector'; +// LogSelector.setLogger(loglevel.getLogger('conseiljs')); +// LogSelector.setLevel('debug'); -import FetchSelector from '../../src/utils/FetchSelector'; -FetchSelector.setFetch(fetch); +// import FetchSelector from '../../src/utils/FetchSelector'; +// FetchSelector.setFetch(fetch); -import { ConseilQueryBuilder } from "../../src/reporting/ConseilQueryBuilder"; -import { ConseilOperator, ConseilSortDirection, ConseilOutput } from "../../src/types/conseil/QueryTypes" -import { ConseilDataClient } from '../../src/reporting/ConseilDataClient' +// import { ConseilQueryBuilder } from "../../src/reporting/ConseilQueryBuilder"; +// import { ConseilOperator, ConseilSortDirection, ConseilOutput } from "../../src/types/conseil/QueryTypes" +// import { ConseilDataClient } from '../../src/reporting/ConseilDataClient' -import { conseilServer } from '../TestAssets'; +// import { conseilServer } from '../TestAssets'; -describe('ConseilDataClient integration test suite', () => { - it('Extract result set as csv', async () => { - let query = ConseilQueryBuilder.blankQuery(); - query = ConseilQueryBuilder.addPredicate(query, 'kind', ConseilOperator.EQ, ['transaction'], false); - query = ConseilQueryBuilder.addOrdering(query, 'block_level', ConseilSortDirection.DESC); - query = ConseilQueryBuilder.setLimit(query, 5); - query = ConseilQueryBuilder.setOutputType(query, ConseilOutput.csv); - const result = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'operations', query); +// describe('ConseilDataClient integration test suite', () => { +// it('Extract result set as csv', async () => { +// let query = ConseilQueryBuilder.blankQuery(); +// query = ConseilQueryBuilder.addPredicate(query, 'kind', ConseilOperator.EQ, ['transaction'], false); +// query = ConseilQueryBuilder.addOrdering(query, 'block_level', ConseilSortDirection.DESC); +// query = ConseilQueryBuilder.setLimit(query, 5); +// query = ConseilQueryBuilder.setOutputType(query, ConseilOutput.csv); +// const result = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'operations', query); - expect(result.length).to.be.greaterThan(100); - expect(result.toString().split('\n').length).to.equal(6); - }); -}); +// expect(result.length).to.be.greaterThan(100); +// expect(result.toString().split('\n').length).to.equal(6); +// }); +// }); diff --git a/integration_test/reporting/tezos/TezosConseilClient.spec.ts b/integration_test/reporting/tezos/TezosConseilClient.spec.ts index 12f0844d..ffbcbdad 100644 --- a/integration_test/reporting/tezos/TezosConseilClient.spec.ts +++ b/integration_test/reporting/tezos/TezosConseilClient.spec.ts @@ -1,145 +1,145 @@ -import 'mocha'; -import { expect } from 'chai'; -import fetch from 'node-fetch'; - -import * as loglevel from 'loglevel'; -import LogSelector from '../../../src/utils/LoggerSelector'; -LogSelector.setLogger(loglevel.getLogger('conseiljs')); -LogSelector.setLevel('debug'); - -import FetchSelector from '../../../src/utils/FetchSelector'; -FetchSelector.setFetch(fetch); - -import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; -import { ConseilOperator, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes' -import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient' -import { OperationKindType } from '../../../src/types/tezos/TezosChainTypes'; -import { conseilServer } from '../../TestAssets'; - -describe('Tezos date interface test suite', () => { - it('retrieve top block', async () => { - const result = await TezosConseilClient.getBlockHead(conseilServer, conseilServer.network); - - expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); - expect(result['baker'].length).to.be.greaterThan(0) - }); - - it('retrieve a block by hash', async () => { - const result = await TezosConseilClient.getBlock(conseilServer, conseilServer.network, 'BKnMKWCeJwRtetQwuY5HRtbrsXPLyACFrygdwnM8jxAYcYEVkdd'); - - expect(result.length).to.equal(1); - }); - - it('retrieve an operation group by hash', async () => { - const result = await TezosConseilClient.getOperationGroup(conseilServer, conseilServer.network, 'ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'); - - expect(result.length).to.equal(1); - }); - - //TODO: getOperationGroups - - it('retrieve an operation group by hash', async () => { - let query = ConseilQueryBuilder.blankQuery(); - query = ConseilQueryBuilder.addPredicate(query, 'operation_group_hash', ConseilOperator.EQ, ['ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'], false); - query = ConseilQueryBuilder.setLimit(query, 10); - - const result = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, query); - - expect(result.length).to.equal(1); - }); - - it('retrieve some blocks', async () => { - let q = ConseilQueryBuilder.blankQuery(); - q = ConseilQueryBuilder.addPredicate(q, 'level', ConseilOperator.LT, [1000], true); - q = ConseilQueryBuilder.addOrdering(q, 'level', ConseilSortDirection.ASC); - q = ConseilQueryBuilder.setLimit(q, 10); - - const result = await TezosConseilClient.getBlocks(conseilServer, conseilServer.network, q); - - expect(result.length).to.equal(10); - expect(parseInt(result[9]['level'])).to.greaterThan(parseInt(result[1]['level'])); - expect(result[9]['predecessor']).to.equal(result[8]['hash']); - }); - - it('retrieve a single an account', async () => { - var result = await TezosConseilClient.getAccount(conseilServer, conseilServer.network, 'tz1bwSatfnvehPG8v5razwMJ7KzJXDBRtxwk'); - - expect(result.length).to.equal(1); - expect(result[0]['account_id']).to.equal('tz1XErrAm8vFBzu69UU74JUSbvsmvXiQBy6e', 'this may vary as the network changes'); - }); - - it('retrieve accounts for a manager address', async () => { - let accountsquery = ConseilQueryBuilder.blankQuery(); - accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'manager', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); - accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'account_id', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], true); - accountsquery = ConseilQueryBuilder.addOrdering(accountsquery, 'block_level', ConseilSortDirection.DESC); - accountsquery = ConseilQueryBuilder.setLimit(accountsquery, 300); - const result = await TezosConseilClient.getAccounts(conseilServer, conseilServer.network, accountsquery); - - expect(result.length).to.be.greaterThan(1, 'this may vary as the network changes'); - expect(result[0]['account_id']).to.equal('KT1SJdeXcP4KkVFF13SYEDFixunJBP7Nwmum', 'this may vary as the network changes'); - }); - - it('retrieve transactions for an account', async () => { - let origin = ConseilQueryBuilder.blankQuery(); - origin = ConseilQueryBuilder.addPredicate(origin, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); - origin = ConseilQueryBuilder.addPredicate(origin, 'source', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); - origin = ConseilQueryBuilder.addOrdering(origin, 'block_level', ConseilSortDirection.DESC); - origin = ConseilQueryBuilder.setLimit(origin, 300); - - let target = ConseilQueryBuilder.blankQuery(); - target = ConseilQueryBuilder.addPredicate(target, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); - target = ConseilQueryBuilder.addPredicate(target, 'destination', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); - target = ConseilQueryBuilder.addOrdering(target, 'block_level', ConseilSortDirection.DESC); - target = ConseilQueryBuilder.setLimit(target, 300); - - var result = await Promise.all([target, origin].map(q => TezosConseilClient.getOperations(conseilServer, conseilServer.network, q))) - .then(responses => responses.reduce((result, r) => { r.forEach(rr => result.push(rr)); return result; })); - - expect(result.length).to.be.greaterThan(10, 'this may vary as the network changes'); - }); - - it('calculate average fees for transaction type operations', async () => { - let operationFeesQuery = ConseilQueryBuilder.blankQuery(); - operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'fee'); - operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); - operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'block_level', ConseilSortDirection.DESC); - operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1000); - - const fees = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, operationFeesQuery); - const sortedfees = fees.map(f => parseInt(f['fee'])).filter(i => !isNaN(i)).sort((a, b) => a - b); - - const lowAverageFee = sortedfees.slice(0, 300).reduce((s, c) => s + c) / 300; - const mediumAverageFee = sortedfees.slice(300, 700).reduce((s, c) => s + c) / 400; - const highAverageFee = sortedfees.slice(700).reduce((s, c) => s + c) / 300; - - expect(lowAverageFee).to.lessThan(mediumAverageFee + 1); - expect(mediumAverageFee).to.lessThan(highAverageFee + 1); - }); - - it('retrieve average fees for transaction type operations', async () => { - let operationFeesQuery = ConseilQueryBuilder.blankQuery(); - operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); - operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); - operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); - operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); - - const fees = await TezosConseilClient.getTezosEntityData(conseilServer, conseilServer.network, 'fees', operationFeesQuery); - - expect(fees[0]['low']).to.lessThan(fees[0]['medium']); - expect(fees[0]['medium']).to.lessThan(fees[0]['high']); - }); - - it('retrieve fee statistics for transaction type operations', async () => { - let operationFeesQuery = ConseilQueryBuilder.blankQuery(); - operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); - operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); - operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); - operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); - - const fees = await TezosConseilClient.getFeeStatistics(conseilServer, conseilServer.network, OperationKindType.Transaction); - - expect(fees[0]['low']).to.lessThan(fees[0]['medium']); - expect(fees[0]['medium']).to.lessThan(fees[0]['high']); - }); -}); +// import 'mocha'; +// import { expect } from 'chai'; +// import fetch from 'node-fetch'; + +// import * as loglevel from 'loglevel'; +// import LogSelector from '../../../src/utils/LoggerSelector'; +// LogSelector.setLogger(loglevel.getLogger('conseiljs')); +// LogSelector.setLevel('debug'); + +// import FetchSelector from '../../../src/utils/FetchSelector'; +// FetchSelector.setFetch(fetch); + +// import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; +// import { ConseilOperator, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes' +// import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient' +// import { OperationKindType } from '../../../src/types/tezos/TezosChainTypes'; +// import { conseilServer } from '../../TestAssets'; + +// describe('Tezos date interface test suite', () => { +// it('retrieve top block', async () => { +// const result = await TezosConseilClient.getBlockHead(conseilServer, conseilServer.network); + +// expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); +// expect(result['baker'].length).to.be.greaterThan(0) +// }); + +// it('retrieve a block by hash', async () => { +// const result = await TezosConseilClient.getBlock(conseilServer, conseilServer.network, 'BKnMKWCeJwRtetQwuY5HRtbrsXPLyACFrygdwnM8jxAYcYEVkdd'); + +// expect(result.length).to.equal(1); +// }); + +// it('retrieve an operation group by hash', async () => { +// const result = await TezosConseilClient.getOperationGroup(conseilServer, conseilServer.network, 'ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'); + +// expect(result.length).to.equal(1); +// }); + +// //TODO: getOperationGroups + +// it('retrieve an operation group by hash', async () => { +// let query = ConseilQueryBuilder.blankQuery(); +// query = ConseilQueryBuilder.addPredicate(query, 'operation_group_hash', ConseilOperator.EQ, ['ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'], false); +// query = ConseilQueryBuilder.setLimit(query, 10); + +// const result = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, query); + +// expect(result.length).to.equal(1); +// }); + +// it('retrieve some blocks', async () => { +// let q = ConseilQueryBuilder.blankQuery(); +// q = ConseilQueryBuilder.addPredicate(q, 'level', ConseilOperator.LT, [1000], true); +// q = ConseilQueryBuilder.addOrdering(q, 'level', ConseilSortDirection.ASC); +// q = ConseilQueryBuilder.setLimit(q, 10); + +// const result = await TezosConseilClient.getBlocks(conseilServer, conseilServer.network, q); + +// expect(result.length).to.equal(10); +// expect(parseInt(result[9]['level'])).to.greaterThan(parseInt(result[1]['level'])); +// expect(result[9]['predecessor']).to.equal(result[8]['hash']); +// }); + +// it('retrieve a single an account', async () => { +// var result = await TezosConseilClient.getAccount(conseilServer, conseilServer.network, 'tz1bwSatfnvehPG8v5razwMJ7KzJXDBRtxwk'); + +// expect(result.length).to.equal(1); +// expect(result[0]['account_id']).to.equal('tz1XErrAm8vFBzu69UU74JUSbvsmvXiQBy6e', 'this may vary as the network changes'); +// }); + +// it('retrieve accounts for a manager address', async () => { +// let accountsquery = ConseilQueryBuilder.blankQuery(); +// accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'manager', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); +// accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'account_id', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], true); +// accountsquery = ConseilQueryBuilder.addOrdering(accountsquery, 'block_level', ConseilSortDirection.DESC); +// accountsquery = ConseilQueryBuilder.setLimit(accountsquery, 300); +// const result = await TezosConseilClient.getAccounts(conseilServer, conseilServer.network, accountsquery); + +// expect(result.length).to.be.greaterThan(1, 'this may vary as the network changes'); +// expect(result[0]['account_id']).to.equal('KT1SJdeXcP4KkVFF13SYEDFixunJBP7Nwmum', 'this may vary as the network changes'); +// }); + +// it('retrieve transactions for an account', async () => { +// let origin = ConseilQueryBuilder.blankQuery(); +// origin = ConseilQueryBuilder.addPredicate(origin, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); +// origin = ConseilQueryBuilder.addPredicate(origin, 'source', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); +// origin = ConseilQueryBuilder.addOrdering(origin, 'block_level', ConseilSortDirection.DESC); +// origin = ConseilQueryBuilder.setLimit(origin, 300); + +// let target = ConseilQueryBuilder.blankQuery(); +// target = ConseilQueryBuilder.addPredicate(target, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); +// target = ConseilQueryBuilder.addPredicate(target, 'destination', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); +// target = ConseilQueryBuilder.addOrdering(target, 'block_level', ConseilSortDirection.DESC); +// target = ConseilQueryBuilder.setLimit(target, 300); + +// var result = await Promise.all([target, origin].map(q => TezosConseilClient.getOperations(conseilServer, conseilServer.network, q))) +// .then(responses => responses.reduce((result, r) => { r.forEach(rr => result.push(rr)); return result; })); + +// expect(result.length).to.be.greaterThan(10, 'this may vary as the network changes'); +// }); + +// it('calculate average fees for transaction type operations', async () => { +// let operationFeesQuery = ConseilQueryBuilder.blankQuery(); +// operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'fee'); +// operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); +// operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'block_level', ConseilSortDirection.DESC); +// operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1000); + +// const fees = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, operationFeesQuery); +// const sortedfees = fees.map(f => parseInt(f['fee'])).filter(i => !isNaN(i)).sort((a, b) => a - b); + +// const lowAverageFee = sortedfees.slice(0, 300).reduce((s, c) => s + c) / 300; +// const mediumAverageFee = sortedfees.slice(300, 700).reduce((s, c) => s + c) / 400; +// const highAverageFee = sortedfees.slice(700).reduce((s, c) => s + c) / 300; + +// expect(lowAverageFee).to.lessThan(mediumAverageFee + 1); +// expect(mediumAverageFee).to.lessThan(highAverageFee + 1); +// }); + +// it('retrieve average fees for transaction type operations', async () => { +// let operationFeesQuery = ConseilQueryBuilder.blankQuery(); +// operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); +// operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); +// operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); +// operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); + +// const fees = await TezosConseilClient.getTezosEntityData(conseilServer, conseilServer.network, 'fees', operationFeesQuery); + +// expect(fees[0]['low']).to.lessThan(fees[0]['medium']); +// expect(fees[0]['medium']).to.lessThan(fees[0]['high']); +// }); + +// it('retrieve fee statistics for transaction type operations', async () => { +// let operationFeesQuery = ConseilQueryBuilder.blankQuery(); +// operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); +// operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); +// operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); +// operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); + +// const fees = await TezosConseilClient.getFeeStatistics(conseilServer, conseilServer.network, OperationKindType.Transaction); + +// expect(fees[0]['low']).to.lessThan(fees[0]['medium']); +// expect(fees[0]['medium']).to.lessThan(fees[0]['high']); +// }); +// }); diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index 975dfb86..2d4aa58d 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -41,26 +41,12 @@ export namespace TezosNodeReader { * Gets the delegate for a smart contract or an implicit account. * * @param {string} server Tezos node to query - * @param {stirng} address The smart contract address or implicit account to query. + * @param {string} accountHash The smart contract address or implicit account to query. + * @returns The address of the delegate, or undefined if there was no delegate set. */ - export async function getDelegate(server: string, address: string): Promise { - const requestUrl = `chains/main/blocks/head/context/contracts/${address}/delegate` - - try { - const delegate = await performGetRequest(server, requestUrl) - // Delegate is a string, even though `performGetRequest` purports to return an object. - return (delegate as unknown) as string - } catch (error) { - const tezosRequestError = error as TezosRequestError - - // Tezos returns a 404 if delegate is not set. - if (tezosRequestError.httpStatus === 404) { - return undefined - } - - // Otherwise, re-throw the error. - throw tezosRequestError - } + export async function getDelegate(server: string, accountHash: string): Promise { + const contractData = await getAccountForBlock(server, 'head', accountHash) + return (contractData.delegate as unknown) as string } /** From 8db8d846843cba278b38051f43682831853d1e00 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 20:26:56 -0700 Subject: [PATCH 50/60] Revert "passing integration tests" This reverts commit 35ce06f348f92db8bb203a0222ac515aa5a30814. --- .../ConseilMetadataClient.spec.ts | 60 ++-- integration_test/LedgerUtils.spec.ts | 34 +- .../TezosHardwareOperations.spec.ts | 286 ++++++++-------- integration_test/TezosHardwareWallet.spec.ts | 22 +- .../tezos/BabylonDelegationHelper.spec.ts | 114 +++---- .../tezos/TezosContractIntrospector.spec.ts | 110 +++--- .../chain/tezos/TezosNodeReader.spec.ts | 67 ++-- .../chain/tezos/TezosNodeWriter.spec.ts | 318 +++++++++--------- .../chain/tezos/lexer/MichelsonParser.spec.ts | 48 +-- .../identity/tezos/TezosLedgerWallet.spec.ts | 34 +- .../reporting/ConseilDataClient.spec.ts | 50 +-- .../tezos/TezosConseilClient.spec.ts | 290 ++++++++-------- src/chain/tezos/TezosNodeReader.ts | 24 +- 13 files changed, 735 insertions(+), 722 deletions(-) diff --git a/integration_test/ConseilMetadataClient.spec.ts b/integration_test/ConseilMetadataClient.spec.ts index 8c086fcc..491e3033 100644 --- a/integration_test/ConseilMetadataClient.spec.ts +++ b/integration_test/ConseilMetadataClient.spec.ts @@ -1,42 +1,42 @@ -// import 'mocha'; -// import { expect } from 'chai'; -// import fetch from 'node-fetch'; +import 'mocha'; +import { expect } from 'chai'; +import fetch from 'node-fetch'; -// import FetchSelector from '../src/utils/FetchSelector'; -// FetchSelector.setFetch(fetch); +import FetchSelector from '../src/utils/FetchSelector'; +FetchSelector.setFetch(fetch); -// import { ConseilMetadataClient } from '../src/reporting/ConseilMetadataClient' -// import { conseilServer } from './TestAssets'; +import { ConseilMetadataClient } from '../src/reporting/ConseilMetadataClient' +import { conseilServer } from './TestAssets'; -// describe('ConseilJS API Wrapper for Conseil protocol v2 test suite', () => { -// it('retrieve list of available platforms', async () => { -// const result = await ConseilMetadataClient.getPlatforms(conseilServer); +describe('ConseilJS API Wrapper for Conseil protocol v2 test suite', () => { + it('retrieve list of available platforms', async () => { + const result = await ConseilMetadataClient.getPlatforms(conseilServer); -// expect(result.map((v) => { return v.name})).to.contain('tezos'); -// }); + expect(result.map((v) => { return v.name})).to.contain('tezos'); + }); -// it('retrieve list of available networks given a platform: tezos', async () => { -// const result = await ConseilMetadataClient.getNetworks(conseilServer, 'tezos'); + it('retrieve list of available networks given a platform: tezos', async () => { + const result = await ConseilMetadataClient.getNetworks(conseilServer, 'tezos'); -// expect(result[0].platform).to.equal('tezos') -// }); + expect(result[0].platform).to.equal('tezos') + }); -// it('retrieve list of available entities for a platform/network combination', async () => { -// const result = await ConseilMetadataClient.getEntities(conseilServer, 'tezos', conseilServer.network); + it('retrieve list of available entities for a platform/network combination', async () => { + const result = await ConseilMetadataClient.getEntities(conseilServer, 'tezos', conseilServer.network); -// expect(result.length).to.greaterThan(1); -// }); + expect(result.length).to.greaterThan(1); + }); -// it('retrieve list of available attributes for a platform/network/entity combination', async () => { -// const result = await ConseilMetadataClient.getAttributes(conseilServer, 'tezos', conseilServer.network, 'accounts'); + it('retrieve list of available attributes for a platform/network/entity combination', async () => { + const result = await ConseilMetadataClient.getAttributes(conseilServer, 'tezos', conseilServer.network, 'accounts'); -// expect(result.length).to.greaterThan(1); -// }); + expect(result.length).to.greaterThan(1); + }); -// it('retrieve list of available attribute values for an entity attribute for a platform/network combination', async () => { -// const result = await ConseilMetadataClient.getAttributeValues(conseilServer, 'tezos', conseilServer.network, 'blocks', 'period_kind'); + it('retrieve list of available attribute values for an entity attribute for a platform/network combination', async () => { + const result = await ConseilMetadataClient.getAttributeValues(conseilServer, 'tezos', conseilServer.network, 'blocks', 'period_kind'); -// expect(result.length).to.be.greaterThan(0); -// expect(result[0]).to.oneOf(['proposal', 'testing']); -// }); -// }); \ No newline at end of file + expect(result.length).to.be.greaterThan(0); + expect(result[0]).to.oneOf(['proposal', 'testing']); + }); +}); \ No newline at end of file diff --git a/integration_test/LedgerUtils.spec.ts b/integration_test/LedgerUtils.spec.ts index 88fd1c89..813da979 100644 --- a/integration_test/LedgerUtils.spec.ts +++ b/integration_test/LedgerUtils.spec.ts @@ -1,23 +1,23 @@ -// import 'mocha'; -// import {expect} from 'chai'; -// import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; +import 'mocha'; +import {expect} from 'chai'; +import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; -// describe('getTezosPublicKey()', () => { -// it('should correctly fetch the root key', async () => { -// const result = await TezosLedgerWallet.getTezosPublicKey("44'/1729'/0'/0'/0'"); +describe('getTezosPublicKey()', () => { + it('should correctly fetch the root key', async () => { + const result = await TezosLedgerWallet.getTezosPublicKey("44'/1729'/0'/0'/0'"); -// expect(result).to.be.a('string') -// }); -// }); + expect(result).to.be.a('string') + }); +}); -// describe('signTezosOperation()', () => { -// it('should correctly sign an operation', async () => { -// const result = await TezosLedgerWallet.signTezosOperation( -// "44'/1729'/0'/0'/0'", -// '0342397c7a82e1f7509513642e573020aeb0aea36ac087139085e42d480cd08520070000d2e495a7ab40156d0a7c35b73d2530a3470fc8700002000000cda3081bd81219ec494b29068dcfd19e427fed9a66abcdc9e9e99ca6478f60e9080000d2e495a7ab40156d0a7c35b73d2530a3470fc870d0860303c80100c0ba99060000e7670f32038107a59a2b9cfefae36ea21f5aa63c00'); +describe('signTezosOperation()', () => { + it('should correctly sign an operation', async () => { + const result = await TezosLedgerWallet.signTezosOperation( + "44'/1729'/0'/0'/0'", + '0342397c7a82e1f7509513642e573020aeb0aea36ac087139085e42d480cd08520070000d2e495a7ab40156d0a7c35b73d2530a3470fc8700002000000cda3081bd81219ec494b29068dcfd19e427fed9a66abcdc9e9e99ca6478f60e9080000d2e495a7ab40156d0a7c35b73d2530a3470fc870d0860303c80100c0ba99060000e7670f32038107a59a2b9cfefae36ea21f5aa63c00'); -// expect(result).to.be.a('Uint8Array') -// }); -// }); + expect(result).to.be.a('Uint8Array') + }); +}); diff --git a/integration_test/TezosHardwareOperations.spec.ts b/integration_test/TezosHardwareOperations.spec.ts index 46cb7cbe..1ece6b76 100644 --- a/integration_test/TezosHardwareOperations.spec.ts +++ b/integration_test/TezosHardwareOperations.spec.ts @@ -1,143 +1,143 @@ -// import {expect} from "chai"; -// import {KeyStore} from "../src/types/wallet/KeyStore"; -// import {TezosWalletUtil} from "../src/identity/tezos/TezosWalletUtil"; -// import {TezosNodeWriter} from "../src"; -// import {TezosLedgerWallet} from "../src/identity/tezos/TezosLedgerWallet"; -// import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; - - -// // const derivationPathIndex = Math.floor(Math.random()*10).toString(); -// const derivationPathIndex = 0; -// const derivationPath = `44'/1729'/0'/0'/` + derivationPathIndex + `'`; - -// function sleep(seconds) { -// const e = new Date().getTime() + (seconds * 1000); -// while (new Date().getTime() <= e) {} -// } - -// describe('Tezos operation functions', () => { -// it('successfully perform operations on a new identity', async (done) => { -// setTimeout(done, 15000); - -// //get fields from tezos alphanet faucet -// // const fundraiserKeys = TezosWalletUtil.unlockFundraiserIdentity( -// // "economy allow chef brave erosion talk panic mirror tail message letter pact remove final pizza", -// // "eriajpqb.sgqzfzjm@tezos.example.org", -// // "NJ73redfI4", -// // "tz1irFsFXR9iT8rW9WJYYKXZPJU2nzaMfyMp" -// // ); - -// // const fundraiserKeySecret = 'e4766f7316aae6b455d7ab886e634a92a24a22dd'; - -// // const mnemonic = TezosWalletUtil.generateMnemonic(); -// // const randomKeys = TezosWalletUtil.unlockIdentityWithMnemonic(mnemonic, ''); -// // const inactiveImplicitAddress = randomKeys.publicKeyHash; -// // const anActiveImplicitAddress = 'tz1is75whxxkVvw2cF2FuRo5ANxZwwJ5nEbc'; -// // const randomDelegatedAddress = 'KT1N5t39Lw7zivvgBN9HJJzUuk64GursRzyc'; -// // const randomBakerAddress1 = 'tz1UmPE44pqWrEgW8sTRs6ED1DgwF7k43ncQ'; -// // const randomBakerAddress2 = 'tz1boot2oCjTjUN6xDNoVmtCLRdh8cc92P1u'; - -// const newAddress = 'tz1bYDK6m4RhCjMmCUTfUeuZ1WaiZZcHQZHN'; - -// const ledgerKeys = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); -// console.log('ledgerKeys----', ledgerKeys); - -// /* -// Uncomment this section if the fundraiser account is inactive - -// console.log("+++++Activating fundraiser account"); -// const activationResult = await TezosNodeWriter.sendIdentityActivationOperation( -// tezosURL, -// fundraiserKeys, -// fundraiserKeySecret, -// derivationPath -// ); -// expect(activationResult.operationGroupID).to.exist; -// sleep(33); - -// */ -// //Send 10tz to Ledger to perform the tests. -// // const receiveResult = await TezosNodeWriter.sendTransactionOperation( -// // tezosURL, -// // fundraiserKeys, -// // ledgerKeys.publicKeyHash, -// // 10000000, -// // 100000, //Protocol 003 minimum fee for inactive implicit accounts is 1387 -// // derivationPath -// // ); -// // expect(receiveResult.operationGroupID).to.exist; - -// // sleep(33); - -// // const inactiveImplicitResult = await TezosNodeWriter.sendTransactionOperation( -// // tezosURL, -// // ledgerKeys, -// // newAddress, -// // 1000000, -// // 300000, // Protocol 003 minimum fee for inactive implicit accounts is 1387 -// // derivationPath -// // ); -// // expect(inactiveImplicitResult.operationGroupID).to.exist; - -// // sleep(33); - -// // const activeImplicitResult = await TezosNodeWriter.sendTransactionOperation( -// // tezosURL, -// // ledgerKeys, -// // anActiveImplicitAddress, -// // 1000000, -// // 300000, // Protocol 003 minimum fee for active implicit accounts is 1100 -// // derivationPath -// // ); -// // expect(activeImplicitResult.operationGroupID).to.exist; - -// // sleep(33); - -// // const delegatedAccountResult = await TezosNodeWriter.sendTransactionOperation( -// // tezosURL, -// // ledgerKeys, -// // randomDelegatedAddress, -// // 1000000, -// // 300000, // Protocol 003 minimum fee for active kt1 accounts is 1100 -// // derivationPath -// // ); -// // expect(delegatedAccountResult.operationGroupID).to.exist; - -// // sleep(33); - -// // const originationResult = await TezosNodeWriter.sendAccountOriginationOperation( -// // tezosURL, -// // ledgerKeys, -// // 1000000, -// // randomBakerAddress1, -// // true, -// // true, -// // 300000, // Protocol 003 minimum fee is 1377 for originations -// // derivationPath -// // ); -// // expect(originationResult.operationGroupID).to.exist; - -// // sleep(33); - -// /* -// // Comment out delegation section in the FIRST run -// // Activate delegation section in the SECOND run. -// // Set delegatedKeyStore.publicKeyHash to the newly originated KT1 address before starting the SECOND run. - -// let delegatedKeyStore = ledgerKeys; -// delegatedKeyStore.publicKeyHash = 'KT1EZgSrodHVN14Mawx91ajKDWybrr3QXuR6'; - -// console.log("+++++Sending delegation operation"); -// const delegationResult = await TezosNodeWriter.sendDelegationOperation( -// tezosURL, -// delegatedKeyStore, -// randomBakerAddress2, -// 300000, // Protocol 003 minimum fee is 1100 for delegations -// derivationPath -// ); -// expect(delegationResult.operationGroupID).to.exist - -// sleep(33); -// */ -// }); -// }); +import {expect} from "chai"; +import {KeyStore} from "../src/types/wallet/KeyStore"; +import {TezosWalletUtil} from "../src/identity/tezos/TezosWalletUtil"; +import {TezosNodeWriter} from "../src"; +import {TezosLedgerWallet} from "../src/identity/tezos/TezosLedgerWallet"; +import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; + + +// const derivationPathIndex = Math.floor(Math.random()*10).toString(); +const derivationPathIndex = 0; +const derivationPath = `44'/1729'/0'/0'/` + derivationPathIndex + `'`; + +function sleep(seconds) { + const e = new Date().getTime() + (seconds * 1000); + while (new Date().getTime() <= e) {} +} + +describe('Tezos operation functions', () => { + it('successfully perform operations on a new identity', async (done) => { + setTimeout(done, 15000); + + //get fields from tezos alphanet faucet + // const fundraiserKeys = TezosWalletUtil.unlockFundraiserIdentity( + // "economy allow chef brave erosion talk panic mirror tail message letter pact remove final pizza", + // "eriajpqb.sgqzfzjm@tezos.example.org", + // "NJ73redfI4", + // "tz1irFsFXR9iT8rW9WJYYKXZPJU2nzaMfyMp" + // ); + + // const fundraiserKeySecret = 'e4766f7316aae6b455d7ab886e634a92a24a22dd'; + + // const mnemonic = TezosWalletUtil.generateMnemonic(); + // const randomKeys = TezosWalletUtil.unlockIdentityWithMnemonic(mnemonic, ''); + // const inactiveImplicitAddress = randomKeys.publicKeyHash; + // const anActiveImplicitAddress = 'tz1is75whxxkVvw2cF2FuRo5ANxZwwJ5nEbc'; + // const randomDelegatedAddress = 'KT1N5t39Lw7zivvgBN9HJJzUuk64GursRzyc'; + // const randomBakerAddress1 = 'tz1UmPE44pqWrEgW8sTRs6ED1DgwF7k43ncQ'; + // const randomBakerAddress2 = 'tz1boot2oCjTjUN6xDNoVmtCLRdh8cc92P1u'; + + const newAddress = 'tz1bYDK6m4RhCjMmCUTfUeuZ1WaiZZcHQZHN'; + + const ledgerKeys = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); + console.log('ledgerKeys----', ledgerKeys); + + /* + Uncomment this section if the fundraiser account is inactive + + console.log("+++++Activating fundraiser account"); + const activationResult = await TezosNodeWriter.sendIdentityActivationOperation( + tezosURL, + fundraiserKeys, + fundraiserKeySecret, + derivationPath + ); + expect(activationResult.operationGroupID).to.exist; + sleep(33); + +*/ + //Send 10tz to Ledger to perform the tests. + // const receiveResult = await TezosNodeWriter.sendTransactionOperation( + // tezosURL, + // fundraiserKeys, + // ledgerKeys.publicKeyHash, + // 10000000, + // 100000, //Protocol 003 minimum fee for inactive implicit accounts is 1387 + // derivationPath + // ); + // expect(receiveResult.operationGroupID).to.exist; + + // sleep(33); + + // const inactiveImplicitResult = await TezosNodeWriter.sendTransactionOperation( + // tezosURL, + // ledgerKeys, + // newAddress, + // 1000000, + // 300000, // Protocol 003 minimum fee for inactive implicit accounts is 1387 + // derivationPath + // ); + // expect(inactiveImplicitResult.operationGroupID).to.exist; + + // sleep(33); + + // const activeImplicitResult = await TezosNodeWriter.sendTransactionOperation( + // tezosURL, + // ledgerKeys, + // anActiveImplicitAddress, + // 1000000, + // 300000, // Protocol 003 minimum fee for active implicit accounts is 1100 + // derivationPath + // ); + // expect(activeImplicitResult.operationGroupID).to.exist; + + // sleep(33); + + // const delegatedAccountResult = await TezosNodeWriter.sendTransactionOperation( + // tezosURL, + // ledgerKeys, + // randomDelegatedAddress, + // 1000000, + // 300000, // Protocol 003 minimum fee for active kt1 accounts is 1100 + // derivationPath + // ); + // expect(delegatedAccountResult.operationGroupID).to.exist; + + // sleep(33); + + // const originationResult = await TezosNodeWriter.sendAccountOriginationOperation( + // tezosURL, + // ledgerKeys, + // 1000000, + // randomBakerAddress1, + // true, + // true, + // 300000, // Protocol 003 minimum fee is 1377 for originations + // derivationPath + // ); + // expect(originationResult.operationGroupID).to.exist; + + // sleep(33); + + /* + // Comment out delegation section in the FIRST run + // Activate delegation section in the SECOND run. + // Set delegatedKeyStore.publicKeyHash to the newly originated KT1 address before starting the SECOND run. + + let delegatedKeyStore = ledgerKeys; + delegatedKeyStore.publicKeyHash = 'KT1EZgSrodHVN14Mawx91ajKDWybrr3QXuR6'; + + console.log("+++++Sending delegation operation"); + const delegationResult = await TezosNodeWriter.sendDelegationOperation( + tezosURL, + delegatedKeyStore, + randomBakerAddress2, + 300000, // Protocol 003 minimum fee is 1100 for delegations + derivationPath + ); + expect(delegationResult.operationGroupID).to.exist + + sleep(33); + */ + }); +}); diff --git a/integration_test/TezosHardwareWallet.spec.ts b/integration_test/TezosHardwareWallet.spec.ts index 27a51a04..d3ab5c51 100644 --- a/integration_test/TezosHardwareWallet.spec.ts +++ b/integration_test/TezosHardwareWallet.spec.ts @@ -1,13 +1,13 @@ -// import 'mocha'; -// import {expect} from 'chai'; -// import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; -// import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; +import 'mocha'; +import {expect} from 'chai'; +import {TezosLedgerWallet} from '../src/identity/tezos/TezosLedgerWallet'; +import {HardwareDeviceType} from "../src/types/wallet/HardwareDeviceType"; -// describe('getTezosPublicKey()', () => { -// it('should correctly fetch the root key', async () => { -// const derivationPath = "44'/1729'/0'/0'"; -// const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); -// console.log(result); -// }); -// }); +describe('getTezosPublicKey()', () => { + it('should correctly fetch the root key', async () => { + const derivationPath = "44'/1729'/0'/0'"; + const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); + console.log(result); + }); +}); diff --git a/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts b/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts index 39779b02..41242265 100644 --- a/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts +++ b/integration_test/chain/tezos/BabylonDelegationHelper.spec.ts @@ -1,57 +1,57 @@ -// import 'mocha'; -// import { expect } from 'chai'; -// import fetch from 'node-fetch'; - -// import * as loglevel from 'loglevel'; -// import LogSelector from '../../../src/utils/LoggerSelector'; -// LogSelector.setLogger(loglevel.getLogger('conseiljs')); -// LogSelector.setLevel('debug'); - -// import FetchSelector from '../../../src/utils/FetchSelector'; -// FetchSelector.setFetch(fetch); - -// import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; -// import { BabylonDelegationHelper } from '../../../src/chain/tezos/contracts/BabylonDelegationHelper'; -// import { tezosServer, conseilServer, keys, bakerAddress } from '../../TestAssets'; - -// describe('BabylonDelegationHelper integration test suite', () => { -// it('Deploy manager.tz P005 "upgrade" contract', async () => { -// const nodeResult = await BabylonDelegationHelper.deployManagerContract(tezosServer, keys, bakerAddress, 20000, 500000); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Set a delegate on the "upgrade" contract', async () => { -// const nodeResult = await BabylonDelegationHelper.setDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 'tz3Q67aMz7gSMiQRcW729sXSfuMtkyAHYfqc', 20000); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Clear the delegate on the "upgrade" contract', async () => { -// const nodeResult = await BabylonDelegationHelper.unSetDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Return delegated funds to the "manager" account', async () => { -// const nodeResult = await BabylonDelegationHelper.withdrawDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Deposit additional funds into the "upgrade" contract', async () => { -// const nodeResult = await BabylonDelegationHelper.depositDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000) -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); -// }); +import 'mocha'; +import { expect } from 'chai'; +import fetch from 'node-fetch'; + +import * as loglevel from 'loglevel'; +import LogSelector from '../../../src/utils/LoggerSelector'; +LogSelector.setLogger(loglevel.getLogger('conseiljs')); +LogSelector.setLevel('debug'); + +import FetchSelector from '../../../src/utils/FetchSelector'; +FetchSelector.setFetch(fetch); + +import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; +import { BabylonDelegationHelper } from '../../../src/chain/tezos/contracts/BabylonDelegationHelper'; +import { tezosServer, conseilServer, keys, bakerAddress } from '../../TestAssets'; + +describe('BabylonDelegationHelper integration test suite', () => { + it('Deploy manager.tz P005 "upgrade" contract', async () => { + const nodeResult = await BabylonDelegationHelper.deployManagerContract(tezosServer, keys, bakerAddress, 20000, 500000); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Set a delegate on the "upgrade" contract', async () => { + const nodeResult = await BabylonDelegationHelper.setDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 'tz3Q67aMz7gSMiQRcW729sXSfuMtkyAHYfqc', 20000); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Clear the delegate on the "upgrade" contract', async () => { + const nodeResult = await BabylonDelegationHelper.unSetDelegate(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Return delegated funds to the "manager" account', async () => { + const nodeResult = await BabylonDelegationHelper.withdrawDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Deposit additional funds into the "upgrade" contract', async () => { + const nodeResult = await BabylonDelegationHelper.depositDelegatedFunds(tezosServer, keys, 'KT1PxkYcmUqjM6Giqu8WKhPyMB5mCVkvWrXg', 20000, 250000) + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = nodeResult["operationGroupID"].replace(/\"/g, '').replace(/\n/, ''); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); +}); diff --git a/integration_test/chain/tezos/TezosContractIntrospector.spec.ts b/integration_test/chain/tezos/TezosContractIntrospector.spec.ts index 354a69f3..ebb02689 100644 --- a/integration_test/chain/tezos/TezosContractIntrospector.spec.ts +++ b/integration_test/chain/tezos/TezosContractIntrospector.spec.ts @@ -1,66 +1,66 @@ -// import 'mocha'; -// import { expect } from 'chai'; -// import fetch from 'node-fetch'; +import 'mocha'; +import { expect } from 'chai'; +import fetch from 'node-fetch'; -// import * as loglevel from 'loglevel'; -// import LogSelector from '../../../src/utils/LoggerSelector'; -// LogSelector.setLogger(loglevel.getLogger('conseiljs')); +import * as loglevel from 'loglevel'; +import LogSelector from '../../../src/utils/LoggerSelector'; +LogSelector.setLogger(loglevel.getLogger('conseiljs')); -// import FetchSelector from '../../../src/utils/FetchSelector'; -// FetchSelector.setFetch(fetch); +import FetchSelector from '../../../src/utils/FetchSelector'; +FetchSelector.setFetch(fetch); -// import { TezosContractIntrospector } from '../../../src/chain/tezos/TezosContractIntrospector'; -// import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil' -// import { EntryPoint } from '../../../src/types/tezos/ContractIntrospectionTypes'; -// import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; -// import { ConseilOperator, ConseilFunction, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes'; -// import { ConseilDataClient } from '../../../src/reporting/ConseilDataClient'; -// import { conseilServer } from '../../TestAssets'; +import { TezosContractIntrospector } from '../../../src/chain/tezos/TezosContractIntrospector'; +import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil' +import { EntryPoint } from '../../../src/types/tezos/ContractIntrospectionTypes'; +import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; +import { ConseilOperator, ConseilFunction, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes'; +import { ConseilDataClient } from '../../../src/reporting/ConseilDataClient'; +import { conseilServer } from '../../TestAssets'; -// describe('TezosContractIntrospector integration test suite', () => { -// it('Process on-chain contracts', async () => { -// const cap = 500; -// let contractQuery = ConseilQueryBuilder.blankQuery(); -// contractQuery = ConseilQueryBuilder.addFields(contractQuery, 'account_id', 'script'); -// contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'account_id', ConseilOperator.STARTSWITH, ['KT1']); -// contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'script', ConseilOperator.ISNULL, [], true); -// contractQuery = ConseilQueryBuilder.addAggregationFunction(contractQuery, 'account_id', ConseilFunction.count); -// contractQuery = ConseilQueryBuilder.addOrdering(contractQuery, 'count_account_id', ConseilSortDirection.DESC); -// contractQuery = ConseilQueryBuilder.setLimit(contractQuery, cap); +describe('TezosContractIntrospector integration test suite', () => { + it('Process on-chain contracts', async () => { + const cap = 500; + let contractQuery = ConseilQueryBuilder.blankQuery(); + contractQuery = ConseilQueryBuilder.addFields(contractQuery, 'account_id', 'script'); + contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'account_id', ConseilOperator.STARTSWITH, ['KT1']); + contractQuery = ConseilQueryBuilder.addPredicate(contractQuery, 'script', ConseilOperator.ISNULL, [], true); + contractQuery = ConseilQueryBuilder.addAggregationFunction(contractQuery, 'account_id', ConseilFunction.count); + contractQuery = ConseilQueryBuilder.addOrdering(contractQuery, 'count_account_id', ConseilSortDirection.DESC); + contractQuery = ConseilQueryBuilder.setLimit(contractQuery, cap); -// const contractList = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'accounts', contractQuery); + const contractList = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'accounts', contractQuery); -// const total = contractList.length; -// let skipped = 0; -// contractList.forEach(r => { -// if (r['script'].startsWith('Unparsable code:')) { skipped++; return; } // accounting for invalid Conseil results + const total = contractList.length; + let skipped = 0; + contractList.forEach(r => { + if (r['script'].startsWith('Unparsable code:')) { skipped++; return; } // accounting for invalid Conseil results -// try { -// let p = TezosContractIntrospector.generateEntryPointsFromCode(r['script']); -// console.log(`processed ${TezosLanguageUtil.preProcessMichelsonScript(r['script'])[0]}`); -// if (p.length === 0) { -// console.log('no entry points found'); -// } else { -// console.log(`entry point${p.length === 1 ? '' : 's' }:`); -// p.forEach(e => { console.log(` ${formatEntryPoint(e)}`); }); -// } -// } catch (error) { -// console.log(`error ${error}\n----\n${r['script']}\n----\n`); -// } -// }); + try { + let p = TezosContractIntrospector.generateEntryPointsFromCode(r['script']); + console.log(`processed ${TezosLanguageUtil.preProcessMichelsonScript(r['script'])[0]}`); + if (p.length === 0) { + console.log('no entry points found'); + } else { + console.log(`entry point${p.length === 1 ? '' : 's' }:`); + p.forEach(e => { console.log(` ${formatEntryPoint(e)}`); }); + } + } catch (error) { + console.log(`error ${error}\n----\n${r['script']}\n----\n`); + } + }); -// console.log(`found ${total} contracts${skipped ? ', skipped ' + skipped : ''}${cap === total ? ', more may be available' : ''}`); -// }); -// }); + console.log(`found ${total} contracts${skipped ? ', skipped ' + skipped : ''}${cap === total ? ', more may be available' : ''}`); + }); +}); -// function formatEntryPoint(entryPoint: EntryPoint){ -// let f = entryPoint.name ? `${entryPoint.name}: ` : '' ; +function formatEntryPoint(entryPoint: EntryPoint){ + let f = entryPoint.name ? `${entryPoint.name}: ` : '' ; -// let args = entryPoint.structure; -// for (let i = 0 ; i < entryPoint.parameters.length; i++) { -// let param = entryPoint.parameters[i]; -// args = args.replace('$PARAM', `${param.type}${param.name ? ' %' + param.name : ''}`); -// } + let args = entryPoint.structure; + for (let i = 0 ; i < entryPoint.parameters.length; i++) { + let param = entryPoint.parameters[i]; + args = args.replace('$PARAM', `${param.type}${param.name ? ' %' + param.name : ''}`); + } -// return f + args; -// } \ No newline at end of file + return f + args; +} \ No newline at end of file diff --git a/integration_test/chain/tezos/TezosNodeReader.spec.ts b/integration_test/chain/tezos/TezosNodeReader.spec.ts index 6433cad0..4c9fcc35 100644 --- a/integration_test/chain/tezos/TezosNodeReader.spec.ts +++ b/integration_test/chain/tezos/TezosNodeReader.spec.ts @@ -10,57 +10,56 @@ import FetchSelector from '../../../src/utils/FetchSelector'; FetchSelector.setFetch(fetch); import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -// import { tezosServer, keys } from '../../TestAssets'; -const tezosServer = "https://rpctest.tzbeta.net" +import { tezosServer, keys } from '../../TestAssets'; describe('TezosNodeReader integration test suite', () => { - // it('Get chain head', async () => { - // const result = await TezosNodeReader.getBlockHead(tezosServer); + it('Get chain head', async () => { + const result = await TezosNodeReader.getBlockHead(tezosServer); - // expect(result['header']['level']).to.be.greaterThan(1); - // }); + expect(result['header']['level']).to.be.greaterThan(1); + }); - // it('Get account counter', async () => { - // const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); + it('Get account counter', async () => { + const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.greaterThan(1); - // }); + expect(result).to.be.greaterThan(1); + }); - // it('Get account reveal status', async () => { - // const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); + it('Get account reveal status', async () => { + const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.true; - // }); + expect(result).to.be.true; + }); - // it('Get account manager key', async () => { - // const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); + it('Get account manager key', async () => { + const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); - // expect(result).to.be.equal(keys.publicKey); - // }); + expect(result).to.be.equal(keys.publicKey); + }); - // it('Get account info', async () => { - // const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); + it('Get account info', async () => { + const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); - // expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); - // }); + expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); + }); - // it('Get account spendable balance', async () => { - // const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); + it('Get account spendable balance', async () => { + const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.greaterThan(10000); - // }); + expect(result).to.be.greaterThan(10000); + }); - // it('Get account funding burn flag', async () => { - // const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); + it('Get account funding burn flag', async () => { + const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); - // expect(result).to.be.false; - // }); + expect(result).to.be.false; + }); - // it('Get head', async () => { - // const result = await TezosNodeReader.getBlock(tezosServer); + it('Get head', async () => { + const result = await TezosNodeReader.getBlock(tezosServer); - // expect(result.header.level).to.be.greaterThan(1); - // }); + expect(result.header.level).to.be.greaterThan(1); + }); it('Gets delegate for a delegated implicit account', async () => { const result = await TezosNodeReader.getDelegate(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); diff --git a/integration_test/chain/tezos/TezosNodeWriter.spec.ts b/integration_test/chain/tezos/TezosNodeWriter.spec.ts index b494f6d1..cd8df814 100644 --- a/integration_test/chain/tezos/TezosNodeWriter.spec.ts +++ b/integration_test/chain/tezos/TezosNodeWriter.spec.ts @@ -1,159 +1,159 @@ -// import 'mocha'; -// import { expect } from 'chai'; -// import fetch from 'node-fetch'; - -// import * as loglevel from 'loglevel'; -// import LogSelector from '../../../src/utils/LoggerSelector'; -// LogSelector.setLogger(loglevel.getLogger('conseiljs')); -// LogSelector.setLevel('debug'); - -// import FetchSelector from '../../../src/utils/FetchSelector'; -// FetchSelector.setFetch(fetch); - -// import { TezosNodeWriter} from '../../../src/chain/tezos/TezosNodeWriter'; -// import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -// import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil'; -// import { TezosWalletUtil} from '../../../src/identity/tezos/TezosWalletUtil'; -// import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; -// import * as TezosTypes from '../../../src/types/tezos/TezosChainTypes'; -// import * as TezosP2PMessageTypes from '../../../src/types/tezos/TezosP2PMessageTypes'; -// import { tezosServer, conseilServer, faucetAccount, keys, transferAddress, bakerAddress, contractAddress } from '../../TestAssets'; - -// function clearRPCOperationGroupHash(hash: string) { -// return hash.replace(/\"/g, '').replace(/\n/, ''); -// } - -// describe('TezosNodeWriter integration test suite', () => { -// it('Activate faucet account', async () => { -// const faucetKeys = await TezosWalletUtil.unlockFundraiserIdentity(faucetAccount.mnemonic.join(' '), faucetAccount.email, faucetAccount.password, faucetAccount.pkh); -// const nodeResult = await TezosNodeWriter.sendIdentityActivationOperation(tezosServer, faucetKeys, faucetAccount.secret); -// expect(nodeResult["operationGroupID"]).to.exist; -// }); - -// it('Reveal faucet account', async () => { -// const nodeResult = await TezosNodeWriter.sendKeyRevealOperation(tezosServer, keys, 50000); -// expect(nodeResult["operationGroupID"]).to.exist; -// }); - -// it('Send XTZ to an account', async () => { -// const nodeResult = await TezosNodeWriter.sendTransactionOperation(tezosServer, keys, transferAddress, 500123, 20000); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Set implicit account delegate', async () => { -// const nodeResult = await TezosNodeWriter.sendDelegationOperation(tezosServer, keys, bakerAddress, 10000); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Originate a simple contract in Michelson', async () => { -// const contract = `parameter string; -// storage string; -// code { CAR ; NIL operation ; PAIR }`; -// const storage = '"Test"'; -// const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Michelson); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 30); -// }); - -// it('Originate a simple contract in Micheline', async () => { -// 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": "hello" }'; -// const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Micheline); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Invoke a contract with a string literal Michelson parameter, default entry point', async () => { -// const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 10000, '', 1000, 100000, 'default', '"Cryptonomicon"', TezosTypes.TezosParameterFormat.Michelson); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Invoke a contract with a complex Michelson parameter, blank entry point', async () => { -// const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '(Pair "message" (Pair "edsigtt7VBCeJjU9XtdCCPcV8VL3xe1XQHehk9Kg78Pxs3VZGXgHGGfktB71jUrK51tiJNybhUQidxxN48W4XWuRjjQwFJ17M1e" "edpkuqoemi1z8wjKxYCMvvshpFU7f71RUXhRyKudwLPBAdhqyj9epe"))', TezosTypes.TezosParameterFormat.Michelson); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Invoke a contract with a Michelson lambda parameter, custom entry point', async () => { -// const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '{ DROP ; NIL operation ; PUSH key_hash "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9" ; SOME ; SET_DELEGATE ; CONS }', TezosTypes.TezosParameterFormat.MichelsonLambda); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Ping a contract on a blank entry point', async () => { -// const nodeResult = await TezosNodeWriter.sendContractPing(tezosServer, keys, contractAddress, 20000, '', 10000, 100000, ''); -// expect(nodeResult["operationGroupID"]).to.exist; - -// const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); -// await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); -// }); - -// it('Estimate transaction gas cost', async () => { -// const counter = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash) + 1; - -// const transaction: TezosP2PMessageTypes.Transaction = { -// destination: contractAddress, -// amount: '0', -// storage_limit: '100', -// gas_limit: '20000', -// counter: counter.toString(), -// fee: '50000', -// source: keys.publicKeyHash, -// kind: 'transaction', -// parameters: { -// entrypoint: '', -// value: JSON.parse(TezosLanguageUtil.translateMichelsonToMicheline('"Cryptonomicon-Cryptonomicon-Cryptonomicon"')) -// } -// }; - -// const result = await TezosNodeWriter.testOperation(tezosServer, [transaction], keys); - -// expect(result.length).to.equal(2); -// expect(result[0]).to.be.greaterThan(10000); -// expect(result[1]).to.be.greaterThan(-1); -// }); - -// /*it('Send a batch of transactions', async () => { -// const destinationA = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRfEbB2JJCffvCFSVCYvKhz2bdp97esBsuUuNLQYZkZu9gFRU3GbcGBs8zRyoJVYh1pkyWRZfHbASuWzrPLDx9tnRwCeUqZ')).publicKeyHash; -// const destinationB = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRtkDq2Z2Z9jMfYjiBvwqky6E7xK8uXxBVnSTdUTALeyqckSdkaSnLSCpx4HCNBBMoLcLo9254tYvBVeoPzfb92xWSHhTSb')).publicKeyHash; - -// let operations = [ -// { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, -// { destination: destinationB, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' } -// ]; -// TezosNodeWriter.queueOperation(tezosServer, operations, keys); - -// operations = [ -// { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, -// ]; -// TezosNodeWriter.queueOperation(tezosServer, operations, keys); - -// await new Promise(resolve => setTimeout(resolve, 40 * 1000)); - -// expect(TezosNodeWriter.getQueueStatus(tezosServer, keys)).to.equal(0); -// });*/ -// }); +import 'mocha'; +import { expect } from 'chai'; +import fetch from 'node-fetch'; + +import * as loglevel from 'loglevel'; +import LogSelector from '../../../src/utils/LoggerSelector'; +LogSelector.setLogger(loglevel.getLogger('conseiljs')); +LogSelector.setLevel('debug'); + +import FetchSelector from '../../../src/utils/FetchSelector'; +FetchSelector.setFetch(fetch); + +import { TezosNodeWriter} from '../../../src/chain/tezos/TezosNodeWriter'; +import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; +import { TezosLanguageUtil } from '../../../src/chain/tezos/TezosLanguageUtil'; +import { TezosWalletUtil} from '../../../src/identity/tezos/TezosWalletUtil'; +import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient'; +import * as TezosTypes from '../../../src/types/tezos/TezosChainTypes'; +import * as TezosP2PMessageTypes from '../../../src/types/tezos/TezosP2PMessageTypes'; +import { tezosServer, conseilServer, faucetAccount, keys, transferAddress, bakerAddress, contractAddress } from '../../TestAssets'; + +function clearRPCOperationGroupHash(hash: string) { + return hash.replace(/\"/g, '').replace(/\n/, ''); +} + +describe('TezosNodeWriter integration test suite', () => { + it('Activate faucet account', async () => { + const faucetKeys = await TezosWalletUtil.unlockFundraiserIdentity(faucetAccount.mnemonic.join(' '), faucetAccount.email, faucetAccount.password, faucetAccount.pkh); + const nodeResult = await TezosNodeWriter.sendIdentityActivationOperation(tezosServer, faucetKeys, faucetAccount.secret); + expect(nodeResult["operationGroupID"]).to.exist; + }); + + it('Reveal faucet account', async () => { + const nodeResult = await TezosNodeWriter.sendKeyRevealOperation(tezosServer, keys, 50000); + expect(nodeResult["operationGroupID"]).to.exist; + }); + + it('Send XTZ to an account', async () => { + const nodeResult = await TezosNodeWriter.sendTransactionOperation(tezosServer, keys, transferAddress, 500123, 20000); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Set implicit account delegate', async () => { + const nodeResult = await TezosNodeWriter.sendDelegationOperation(tezosServer, keys, bakerAddress, 10000); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Originate a simple contract in Michelson', async () => { + const contract = `parameter string; + storage string; + code { CAR ; NIL operation ; PAIR }`; + const storage = '"Test"'; + const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Michelson); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 30); + }); + + it('Originate a simple contract in Micheline', async () => { + 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": "hello" }'; + const nodeResult = await TezosNodeWriter.sendContractOriginationOperation(tezosServer, keys, 10000, undefined, 10000, '', 10000, 20000, contract, storage, TezosTypes.TezosParameterFormat.Micheline); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Invoke a contract with a string literal Michelson parameter, default entry point', async () => { + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 10000, '', 1000, 100000, 'default', '"Cryptonomicon"', TezosTypes.TezosParameterFormat.Michelson); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Invoke a contract with a complex Michelson parameter, blank entry point', async () => { + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '(Pair "message" (Pair "edsigtt7VBCeJjU9XtdCCPcV8VL3xe1XQHehk9Kg78Pxs3VZGXgHGGfktB71jUrK51tiJNybhUQidxxN48W4XWuRjjQwFJ17M1e" "edpkuqoemi1z8wjKxYCMvvshpFU7f71RUXhRyKudwLPBAdhqyj9epe"))', TezosTypes.TezosParameterFormat.Michelson); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Invoke a contract with a Michelson lambda parameter, custom entry point', async () => { + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keys, contractAddress, 10000, 20000, '', 10000, 100000, '', '{ DROP ; NIL operation ; PUSH key_hash "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9" ; SOME ; SET_DELEGATE ; CONS }', TezosTypes.TezosParameterFormat.MichelsonLambda); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Ping a contract on a blank entry point', async () => { + const nodeResult = await TezosNodeWriter.sendContractPing(tezosServer, keys, contractAddress, 20000, '', 10000, 100000, ''); + expect(nodeResult["operationGroupID"]).to.exist; + + const groupid = clearRPCOperationGroupHash(nodeResult["operationGroupID"]); + await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, 31); + }); + + it('Estimate transaction gas cost', async () => { + const counter = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash) + 1; + + const transaction: TezosP2PMessageTypes.Transaction = { + destination: contractAddress, + amount: '0', + storage_limit: '100', + gas_limit: '20000', + counter: counter.toString(), + fee: '50000', + source: keys.publicKeyHash, + kind: 'transaction', + parameters: { + entrypoint: '', + value: JSON.parse(TezosLanguageUtil.translateMichelsonToMicheline('"Cryptonomicon-Cryptonomicon-Cryptonomicon"')) + } + }; + + const result = await TezosNodeWriter.testOperation(tezosServer, [transaction], keys); + + expect(result.length).to.equal(2); + expect(result[0]).to.be.greaterThan(10000); + expect(result[1]).to.be.greaterThan(-1); + }); + + /*it('Send a batch of transactions', async () => { + const destinationA = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRfEbB2JJCffvCFSVCYvKhz2bdp97esBsuUuNLQYZkZu9gFRU3GbcGBs8zRyoJVYh1pkyWRZfHbASuWzrPLDx9tnRwCeUqZ')).publicKeyHash; + const destinationB = (await TezosWalletUtil.restoreIdentityWithSecretKey('edskRtkDq2Z2Z9jMfYjiBvwqky6E7xK8uXxBVnSTdUTALeyqckSdkaSnLSCpx4HCNBBMoLcLo9254tYvBVeoPzfb92xWSHhTSb')).publicKeyHash; + + let operations = [ + { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, + { destination: destinationB, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' } + ]; + TezosNodeWriter.queueOperation(tezosServer, operations, keys); + + operations = [ + { destination: destinationA, amount: '100000', storage_limit: '300', gas_limit: '10600', counter: '0', fee: '10000', source: keys.publicKeyHash, kind: 'transaction' }, + ]; + TezosNodeWriter.queueOperation(tezosServer, operations, keys); + + await new Promise(resolve => setTimeout(resolve, 40 * 1000)); + + expect(TezosNodeWriter.getQueueStatus(tezosServer, keys)).to.equal(0); + });*/ +}); diff --git a/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts b/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts index a9160156..a8811e6e 100644 --- a/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts +++ b/integration_test/chain/tezos/lexer/MichelsonParser.spec.ts @@ -1,30 +1,30 @@ -// import 'mocha'; -// import { expect } from 'chai'; +import 'mocha'; +import { expect } from 'chai'; -// import * as Michelson from '../../../../src/chain/tezos/lexer/Michelson'; -// import * as nearley from 'nearley'; +import * as Michelson from '../../../../src/chain/tezos/lexer/Michelson'; +import * as nearley from 'nearley'; -// function michelsonToMicheline(code: string): string { -// const processedCode = code.trim().split('\n').map(l => l.replace(/\#[\s\S]+$/, '').trim()).join(' '); +function michelsonToMicheline(code: string): string { + const processedCode = code.trim().split('\n').map(l => l.replace(/\#[\s\S]+$/, '').trim()).join(' '); -// const parser = new nearley.Parser(nearley.Grammar.fromCompiled(Michelson.default)); -// parser.feed(processedCode); -// return parser.results.join(' '); -// } + const parser = new nearley.Parser(nearley.Grammar.fromCompiled(Michelson.default)); + parser.feed(processedCode); + return parser.results.join(' '); +} -// const baseURL = 'https://gitlab.com/tezos/tezos/tree/master/src/bin_client/test/contracts/attic'; -// const officialContractSamples = ['accounts.tz', 'add1.tz', 'add1_list.tz']; -// const michelineTranslations = {'accounts.tz': '', 'add1.tz': '', 'add1_list.tz': ''}; +const baseURL = 'https://gitlab.com/tezos/tezos/tree/master/src/bin_client/test/contracts/attic'; +const officialContractSamples = ['accounts.tz', 'add1.tz', 'add1_list.tz']; +const michelineTranslations = {'accounts.tz': '', 'add1.tz': '', 'add1_list.tz': ''}; -// /*describe('Michelson/Micheline transpiler tests', () => { -// for (let i = 0; i < officialContractSamples.length; i++) { -// const contractName = officialContractSamples[i]; -// it(`Contract test: ${contractName}`, async () => { -// const code = await request.get(`${baseURL}/${contractName}`) -// .then(res => res.toString()) -// .catch(err => { throw new Error(`Failed to get ${contractName}: ${err}`); }); +/*describe('Michelson/Micheline transpiler tests', () => { + for (let i = 0; i < officialContractSamples.length; i++) { + const contractName = officialContractSamples[i]; + it(`Contract test: ${contractName}`, async () => { + const code = await request.get(`${baseURL}/${contractName}`) + .then(res => res.toString()) + .catch(err => { throw new Error(`Failed to get ${contractName}: ${err}`); }); -// expect(michelsonToMicheline(code)).to.equal(michelineTranslations[contractName]); -// }); -// } -// });*/ + expect(michelsonToMicheline(code)).to.equal(michelineTranslations[contractName]); + }); + } +});*/ diff --git a/integration_test/identity/tezos/TezosLedgerWallet.spec.ts b/integration_test/identity/tezos/TezosLedgerWallet.spec.ts index 832e2254..e3cc11ff 100644 --- a/integration_test/identity/tezos/TezosLedgerWallet.spec.ts +++ b/integration_test/identity/tezos/TezosLedgerWallet.spec.ts @@ -1,21 +1,21 @@ -// import 'mocha'; -// import { expect } from 'chai'; +import 'mocha'; +import { expect } from 'chai'; -// import * as loglevel from 'loglevel'; -// import LogSelector from '../../../src/utils/LoggerSelector'; -// LogSelector.setLogger(loglevel.getLogger('conseiljs')); -// LogSelector.setLevel('debug'); +import * as loglevel from 'loglevel'; +import LogSelector from '../../../src/utils/LoggerSelector'; +LogSelector.setLogger(loglevel.getLogger('conseiljs')); +LogSelector.setLevel('debug'); -// import { TezosLedgerWallet } from '../../../src/identity/tezos/TezosLedgerWallet'; -// import {HardwareDeviceType} from "../../../src/types/wallet/HardwareDeviceType"; +import { TezosLedgerWallet } from '../../../src/identity/tezos/TezosLedgerWallet'; +import {HardwareDeviceType} from "../../../src/types/wallet/HardwareDeviceType"; -// describe('Ledger hardware signer integration tests', () => { -// it('unlockAddress', async () => { -// const derivationPath = "44'/1729'/0'/0'"; -// const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); -// console.log(result); +describe('Ledger hardware signer integration tests', () => { + it('unlockAddress', async () => { + const derivationPath = "44'/1729'/0'/0'"; + const result = await TezosLedgerWallet.unlockAddress(HardwareDeviceType.LedgerNanoS, derivationPath); + console.log(result); -// //expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); -// //expect(result['baker'].length).to.be.greaterThan(0) -// }); -// }); + //expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); + //expect(result['baker'].length).to.be.greaterThan(0) + }); +}); diff --git a/integration_test/reporting/ConseilDataClient.spec.ts b/integration_test/reporting/ConseilDataClient.spec.ts index a51007c4..2992a040 100644 --- a/integration_test/reporting/ConseilDataClient.spec.ts +++ b/integration_test/reporting/ConseilDataClient.spec.ts @@ -1,31 +1,31 @@ -// import 'mocha'; -// import { expect } from 'chai'; -// import fetch from 'node-fetch'; +import 'mocha'; +import { expect } from 'chai'; +import fetch from 'node-fetch'; -// import * as loglevel from 'loglevel'; -// import LogSelector from '../../src/utils/LoggerSelector'; -// LogSelector.setLogger(loglevel.getLogger('conseiljs')); -// LogSelector.setLevel('debug'); +import * as loglevel from 'loglevel'; +import LogSelector from '../../src/utils/LoggerSelector'; +LogSelector.setLogger(loglevel.getLogger('conseiljs')); +LogSelector.setLevel('debug'); -// import FetchSelector from '../../src/utils/FetchSelector'; -// FetchSelector.setFetch(fetch); +import FetchSelector from '../../src/utils/FetchSelector'; +FetchSelector.setFetch(fetch); -// import { ConseilQueryBuilder } from "../../src/reporting/ConseilQueryBuilder"; -// import { ConseilOperator, ConseilSortDirection, ConseilOutput } from "../../src/types/conseil/QueryTypes" -// import { ConseilDataClient } from '../../src/reporting/ConseilDataClient' +import { ConseilQueryBuilder } from "../../src/reporting/ConseilQueryBuilder"; +import { ConseilOperator, ConseilSortDirection, ConseilOutput } from "../../src/types/conseil/QueryTypes" +import { ConseilDataClient } from '../../src/reporting/ConseilDataClient' -// import { conseilServer } from '../TestAssets'; +import { conseilServer } from '../TestAssets'; -// describe('ConseilDataClient integration test suite', () => { -// it('Extract result set as csv', async () => { -// let query = ConseilQueryBuilder.blankQuery(); -// query = ConseilQueryBuilder.addPredicate(query, 'kind', ConseilOperator.EQ, ['transaction'], false); -// query = ConseilQueryBuilder.addOrdering(query, 'block_level', ConseilSortDirection.DESC); -// query = ConseilQueryBuilder.setLimit(query, 5); -// query = ConseilQueryBuilder.setOutputType(query, ConseilOutput.csv); -// const result = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'operations', query); +describe('ConseilDataClient integration test suite', () => { + it('Extract result set as csv', async () => { + let query = ConseilQueryBuilder.blankQuery(); + query = ConseilQueryBuilder.addPredicate(query, 'kind', ConseilOperator.EQ, ['transaction'], false); + query = ConseilQueryBuilder.addOrdering(query, 'block_level', ConseilSortDirection.DESC); + query = ConseilQueryBuilder.setLimit(query, 5); + query = ConseilQueryBuilder.setOutputType(query, ConseilOutput.csv); + const result = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'operations', query); -// expect(result.length).to.be.greaterThan(100); -// expect(result.toString().split('\n').length).to.equal(6); -// }); -// }); + expect(result.length).to.be.greaterThan(100); + expect(result.toString().split('\n').length).to.equal(6); + }); +}); diff --git a/integration_test/reporting/tezos/TezosConseilClient.spec.ts b/integration_test/reporting/tezos/TezosConseilClient.spec.ts index ffbcbdad..12f0844d 100644 --- a/integration_test/reporting/tezos/TezosConseilClient.spec.ts +++ b/integration_test/reporting/tezos/TezosConseilClient.spec.ts @@ -1,145 +1,145 @@ -// import 'mocha'; -// import { expect } from 'chai'; -// import fetch from 'node-fetch'; - -// import * as loglevel from 'loglevel'; -// import LogSelector from '../../../src/utils/LoggerSelector'; -// LogSelector.setLogger(loglevel.getLogger('conseiljs')); -// LogSelector.setLevel('debug'); - -// import FetchSelector from '../../../src/utils/FetchSelector'; -// FetchSelector.setFetch(fetch); - -// import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; -// import { ConseilOperator, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes' -// import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient' -// import { OperationKindType } from '../../../src/types/tezos/TezosChainTypes'; -// import { conseilServer } from '../../TestAssets'; - -// describe('Tezos date interface test suite', () => { -// it('retrieve top block', async () => { -// const result = await TezosConseilClient.getBlockHead(conseilServer, conseilServer.network); - -// expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); -// expect(result['baker'].length).to.be.greaterThan(0) -// }); - -// it('retrieve a block by hash', async () => { -// const result = await TezosConseilClient.getBlock(conseilServer, conseilServer.network, 'BKnMKWCeJwRtetQwuY5HRtbrsXPLyACFrygdwnM8jxAYcYEVkdd'); - -// expect(result.length).to.equal(1); -// }); - -// it('retrieve an operation group by hash', async () => { -// const result = await TezosConseilClient.getOperationGroup(conseilServer, conseilServer.network, 'ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'); - -// expect(result.length).to.equal(1); -// }); - -// //TODO: getOperationGroups - -// it('retrieve an operation group by hash', async () => { -// let query = ConseilQueryBuilder.blankQuery(); -// query = ConseilQueryBuilder.addPredicate(query, 'operation_group_hash', ConseilOperator.EQ, ['ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'], false); -// query = ConseilQueryBuilder.setLimit(query, 10); - -// const result = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, query); - -// expect(result.length).to.equal(1); -// }); - -// it('retrieve some blocks', async () => { -// let q = ConseilQueryBuilder.blankQuery(); -// q = ConseilQueryBuilder.addPredicate(q, 'level', ConseilOperator.LT, [1000], true); -// q = ConseilQueryBuilder.addOrdering(q, 'level', ConseilSortDirection.ASC); -// q = ConseilQueryBuilder.setLimit(q, 10); - -// const result = await TezosConseilClient.getBlocks(conseilServer, conseilServer.network, q); - -// expect(result.length).to.equal(10); -// expect(parseInt(result[9]['level'])).to.greaterThan(parseInt(result[1]['level'])); -// expect(result[9]['predecessor']).to.equal(result[8]['hash']); -// }); - -// it('retrieve a single an account', async () => { -// var result = await TezosConseilClient.getAccount(conseilServer, conseilServer.network, 'tz1bwSatfnvehPG8v5razwMJ7KzJXDBRtxwk'); - -// expect(result.length).to.equal(1); -// expect(result[0]['account_id']).to.equal('tz1XErrAm8vFBzu69UU74JUSbvsmvXiQBy6e', 'this may vary as the network changes'); -// }); - -// it('retrieve accounts for a manager address', async () => { -// let accountsquery = ConseilQueryBuilder.blankQuery(); -// accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'manager', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); -// accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'account_id', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], true); -// accountsquery = ConseilQueryBuilder.addOrdering(accountsquery, 'block_level', ConseilSortDirection.DESC); -// accountsquery = ConseilQueryBuilder.setLimit(accountsquery, 300); -// const result = await TezosConseilClient.getAccounts(conseilServer, conseilServer.network, accountsquery); - -// expect(result.length).to.be.greaterThan(1, 'this may vary as the network changes'); -// expect(result[0]['account_id']).to.equal('KT1SJdeXcP4KkVFF13SYEDFixunJBP7Nwmum', 'this may vary as the network changes'); -// }); - -// it('retrieve transactions for an account', async () => { -// let origin = ConseilQueryBuilder.blankQuery(); -// origin = ConseilQueryBuilder.addPredicate(origin, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); -// origin = ConseilQueryBuilder.addPredicate(origin, 'source', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); -// origin = ConseilQueryBuilder.addOrdering(origin, 'block_level', ConseilSortDirection.DESC); -// origin = ConseilQueryBuilder.setLimit(origin, 300); - -// let target = ConseilQueryBuilder.blankQuery(); -// target = ConseilQueryBuilder.addPredicate(target, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); -// target = ConseilQueryBuilder.addPredicate(target, 'destination', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); -// target = ConseilQueryBuilder.addOrdering(target, 'block_level', ConseilSortDirection.DESC); -// target = ConseilQueryBuilder.setLimit(target, 300); - -// var result = await Promise.all([target, origin].map(q => TezosConseilClient.getOperations(conseilServer, conseilServer.network, q))) -// .then(responses => responses.reduce((result, r) => { r.forEach(rr => result.push(rr)); return result; })); - -// expect(result.length).to.be.greaterThan(10, 'this may vary as the network changes'); -// }); - -// it('calculate average fees for transaction type operations', async () => { -// let operationFeesQuery = ConseilQueryBuilder.blankQuery(); -// operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'fee'); -// operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); -// operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'block_level', ConseilSortDirection.DESC); -// operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1000); - -// const fees = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, operationFeesQuery); -// const sortedfees = fees.map(f => parseInt(f['fee'])).filter(i => !isNaN(i)).sort((a, b) => a - b); - -// const lowAverageFee = sortedfees.slice(0, 300).reduce((s, c) => s + c) / 300; -// const mediumAverageFee = sortedfees.slice(300, 700).reduce((s, c) => s + c) / 400; -// const highAverageFee = sortedfees.slice(700).reduce((s, c) => s + c) / 300; - -// expect(lowAverageFee).to.lessThan(mediumAverageFee + 1); -// expect(mediumAverageFee).to.lessThan(highAverageFee + 1); -// }); - -// it('retrieve average fees for transaction type operations', async () => { -// let operationFeesQuery = ConseilQueryBuilder.blankQuery(); -// operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); -// operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); -// operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); -// operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); - -// const fees = await TezosConseilClient.getTezosEntityData(conseilServer, conseilServer.network, 'fees', operationFeesQuery); - -// expect(fees[0]['low']).to.lessThan(fees[0]['medium']); -// expect(fees[0]['medium']).to.lessThan(fees[0]['high']); -// }); - -// it('retrieve fee statistics for transaction type operations', async () => { -// let operationFeesQuery = ConseilQueryBuilder.blankQuery(); -// operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); -// operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); -// operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); -// operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); - -// const fees = await TezosConseilClient.getFeeStatistics(conseilServer, conseilServer.network, OperationKindType.Transaction); - -// expect(fees[0]['low']).to.lessThan(fees[0]['medium']); -// expect(fees[0]['medium']).to.lessThan(fees[0]['high']); -// }); -// }); +import 'mocha'; +import { expect } from 'chai'; +import fetch from 'node-fetch'; + +import * as loglevel from 'loglevel'; +import LogSelector from '../../../src/utils/LoggerSelector'; +LogSelector.setLogger(loglevel.getLogger('conseiljs')); +LogSelector.setLevel('debug'); + +import FetchSelector from '../../../src/utils/FetchSelector'; +FetchSelector.setFetch(fetch); + +import { ConseilQueryBuilder } from '../../../src/reporting/ConseilQueryBuilder'; +import { ConseilOperator, ConseilSortDirection } from '../../../src/types/conseil/QueryTypes' +import { TezosConseilClient } from '../../../src/reporting/tezos/TezosConseilClient' +import { OperationKindType } from '../../../src/types/tezos/TezosChainTypes'; +import { conseilServer } from '../../TestAssets'; + +describe('Tezos date interface test suite', () => { + it('retrieve top block', async () => { + const result = await TezosConseilClient.getBlockHead(conseilServer, conseilServer.network); + + expect(result['level']).to.be.greaterThan(52466, 'this may vary as the network changes'); + expect(result['baker'].length).to.be.greaterThan(0) + }); + + it('retrieve a block by hash', async () => { + const result = await TezosConseilClient.getBlock(conseilServer, conseilServer.network, 'BKnMKWCeJwRtetQwuY5HRtbrsXPLyACFrygdwnM8jxAYcYEVkdd'); + + expect(result.length).to.equal(1); + }); + + it('retrieve an operation group by hash', async () => { + const result = await TezosConseilClient.getOperationGroup(conseilServer, conseilServer.network, 'ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'); + + expect(result.length).to.equal(1); + }); + + //TODO: getOperationGroups + + it('retrieve an operation group by hash', async () => { + let query = ConseilQueryBuilder.blankQuery(); + query = ConseilQueryBuilder.addPredicate(query, 'operation_group_hash', ConseilOperator.EQ, ['ooH1GMyC7zHRP7SJgqnjzoxs5DshEUrYNehAQm9j5PUxMA4TdeP'], false); + query = ConseilQueryBuilder.setLimit(query, 10); + + const result = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, query); + + expect(result.length).to.equal(1); + }); + + it('retrieve some blocks', async () => { + let q = ConseilQueryBuilder.blankQuery(); + q = ConseilQueryBuilder.addPredicate(q, 'level', ConseilOperator.LT, [1000], true); + q = ConseilQueryBuilder.addOrdering(q, 'level', ConseilSortDirection.ASC); + q = ConseilQueryBuilder.setLimit(q, 10); + + const result = await TezosConseilClient.getBlocks(conseilServer, conseilServer.network, q); + + expect(result.length).to.equal(10); + expect(parseInt(result[9]['level'])).to.greaterThan(parseInt(result[1]['level'])); + expect(result[9]['predecessor']).to.equal(result[8]['hash']); + }); + + it('retrieve a single an account', async () => { + var result = await TezosConseilClient.getAccount(conseilServer, conseilServer.network, 'tz1bwSatfnvehPG8v5razwMJ7KzJXDBRtxwk'); + + expect(result.length).to.equal(1); + expect(result[0]['account_id']).to.equal('tz1XErrAm8vFBzu69UU74JUSbvsmvXiQBy6e', 'this may vary as the network changes'); + }); + + it('retrieve accounts for a manager address', async () => { + let accountsquery = ConseilQueryBuilder.blankQuery(); + accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'manager', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); + accountsquery = ConseilQueryBuilder.addPredicate(accountsquery, 'account_id', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], true); + accountsquery = ConseilQueryBuilder.addOrdering(accountsquery, 'block_level', ConseilSortDirection.DESC); + accountsquery = ConseilQueryBuilder.setLimit(accountsquery, 300); + const result = await TezosConseilClient.getAccounts(conseilServer, conseilServer.network, accountsquery); + + expect(result.length).to.be.greaterThan(1, 'this may vary as the network changes'); + expect(result[0]['account_id']).to.equal('KT1SJdeXcP4KkVFF13SYEDFixunJBP7Nwmum', 'this may vary as the network changes'); + }); + + it('retrieve transactions for an account', async () => { + let origin = ConseilQueryBuilder.blankQuery(); + origin = ConseilQueryBuilder.addPredicate(origin, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); + origin = ConseilQueryBuilder.addPredicate(origin, 'source', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); + origin = ConseilQueryBuilder.addOrdering(origin, 'block_level', ConseilSortDirection.DESC); + origin = ConseilQueryBuilder.setLimit(origin, 300); + + let target = ConseilQueryBuilder.blankQuery(); + target = ConseilQueryBuilder.addPredicate(target, 'kind', ConseilOperator.IN, ['transaction', 'activate_account', 'reveal', 'origination', 'delegation'], false); + target = ConseilQueryBuilder.addPredicate(target, 'destination', ConseilOperator.EQ, ['tz1aCy8b6Ls4Gz7m5SbANjtMPiH6dZr9nnS2'], false); + target = ConseilQueryBuilder.addOrdering(target, 'block_level', ConseilSortDirection.DESC); + target = ConseilQueryBuilder.setLimit(target, 300); + + var result = await Promise.all([target, origin].map(q => TezosConseilClient.getOperations(conseilServer, conseilServer.network, q))) + .then(responses => responses.reduce((result, r) => { r.forEach(rr => result.push(rr)); return result; })); + + expect(result.length).to.be.greaterThan(10, 'this may vary as the network changes'); + }); + + it('calculate average fees for transaction type operations', async () => { + let operationFeesQuery = ConseilQueryBuilder.blankQuery(); + operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'fee'); + operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); + operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'block_level', ConseilSortDirection.DESC); + operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1000); + + const fees = await TezosConseilClient.getOperations(conseilServer, conseilServer.network, operationFeesQuery); + const sortedfees = fees.map(f => parseInt(f['fee'])).filter(i => !isNaN(i)).sort((a, b) => a - b); + + const lowAverageFee = sortedfees.slice(0, 300).reduce((s, c) => s + c) / 300; + const mediumAverageFee = sortedfees.slice(300, 700).reduce((s, c) => s + c) / 400; + const highAverageFee = sortedfees.slice(700).reduce((s, c) => s + c) / 300; + + expect(lowAverageFee).to.lessThan(mediumAverageFee + 1); + expect(mediumAverageFee).to.lessThan(highAverageFee + 1); + }); + + it('retrieve average fees for transaction type operations', async () => { + let operationFeesQuery = ConseilQueryBuilder.blankQuery(); + operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); + operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); + operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); + operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); + + const fees = await TezosConseilClient.getTezosEntityData(conseilServer, conseilServer.network, 'fees', operationFeesQuery); + + expect(fees[0]['low']).to.lessThan(fees[0]['medium']); + expect(fees[0]['medium']).to.lessThan(fees[0]['high']); + }); + + it('retrieve fee statistics for transaction type operations', async () => { + let operationFeesQuery = ConseilQueryBuilder.blankQuery(); + operationFeesQuery = ConseilQueryBuilder.addFields(operationFeesQuery, 'low', 'medium', 'high'); + operationFeesQuery = ConseilQueryBuilder.addPredicate(operationFeesQuery, 'kind', ConseilOperator.EQ, ['transaction'], false); + operationFeesQuery = ConseilQueryBuilder.addOrdering(operationFeesQuery, 'timestamp', ConseilSortDirection.DESC); + operationFeesQuery = ConseilQueryBuilder.setLimit(operationFeesQuery, 1); + + const fees = await TezosConseilClient.getFeeStatistics(conseilServer, conseilServer.network, OperationKindType.Transaction); + + expect(fees[0]['low']).to.lessThan(fees[0]['medium']); + expect(fees[0]['medium']).to.lessThan(fees[0]['high']); + }); +}); diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index 2d4aa58d..975dfb86 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -41,12 +41,26 @@ export namespace TezosNodeReader { * Gets the delegate for a smart contract or an implicit account. * * @param {string} server Tezos node to query - * @param {string} accountHash The smart contract address or implicit account to query. - * @returns The address of the delegate, or undefined if there was no delegate set. + * @param {stirng} address The smart contract address or implicit account to query. */ - export async function getDelegate(server: string, accountHash: string): Promise { - const contractData = await getAccountForBlock(server, 'head', accountHash) - return (contractData.delegate as unknown) as string + export async function getDelegate(server: string, address: string): Promise { + const requestUrl = `chains/main/blocks/head/context/contracts/${address}/delegate` + + try { + const delegate = await performGetRequest(server, requestUrl) + // Delegate is a string, even though `performGetRequest` purports to return an object. + return (delegate as unknown) as string + } catch (error) { + const tezosRequestError = error as TezosRequestError + + // Tezos returns a 404 if delegate is not set. + if (tezosRequestError.httpStatus === 404) { + return undefined + } + + // Otherwise, re-throw the error. + throw tezosRequestError + } } /** From 9738216cfc2301c0ab6373692a4a4162041819c1 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 20:27:19 -0700 Subject: [PATCH 51/60] tests --- .../chain/tezos/TezosNodeReader.spec.ts | 67 ++++++++++--------- src/chain/tezos/TezosNodeReader.ts | 24 ++----- 2 files changed, 39 insertions(+), 52 deletions(-) diff --git a/integration_test/chain/tezos/TezosNodeReader.spec.ts b/integration_test/chain/tezos/TezosNodeReader.spec.ts index 4c9fcc35..6433cad0 100644 --- a/integration_test/chain/tezos/TezosNodeReader.spec.ts +++ b/integration_test/chain/tezos/TezosNodeReader.spec.ts @@ -10,56 +10,57 @@ import FetchSelector from '../../../src/utils/FetchSelector'; FetchSelector.setFetch(fetch); import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -import { tezosServer, keys } from '../../TestAssets'; +// import { tezosServer, keys } from '../../TestAssets'; +const tezosServer = "https://rpctest.tzbeta.net" describe('TezosNodeReader integration test suite', () => { - it('Get chain head', async () => { - const result = await TezosNodeReader.getBlockHead(tezosServer); + // it('Get chain head', async () => { + // const result = await TezosNodeReader.getBlockHead(tezosServer); - expect(result['header']['level']).to.be.greaterThan(1); - }); + // expect(result['header']['level']).to.be.greaterThan(1); + // }); - it('Get account counter', async () => { - const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); + // it('Get account counter', async () => { + // const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.greaterThan(1); - }); + // expect(result).to.be.greaterThan(1); + // }); - it('Get account reveal status', async () => { - const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); + // it('Get account reveal status', async () => { + // const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.true; - }); + // expect(result).to.be.true; + // }); - it('Get account manager key', async () => { - const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); + // it('Get account manager key', async () => { + // const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); - expect(result).to.be.equal(keys.publicKey); - }); + // expect(result).to.be.equal(keys.publicKey); + // }); - it('Get account info', async () => { - const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); + // it('Get account info', async () => { + // const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); - expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); - }); + // expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); + // }); - it('Get account spendable balance', async () => { - const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); + // it('Get account spendable balance', async () => { + // const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); - expect(result).to.be.greaterThan(10000); - }); + // expect(result).to.be.greaterThan(10000); + // }); - it('Get account funding burn flag', async () => { - const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); + // it('Get account funding burn flag', async () => { + // const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); - expect(result).to.be.false; - }); + // expect(result).to.be.false; + // }); - it('Get head', async () => { - const result = await TezosNodeReader.getBlock(tezosServer); + // it('Get head', async () => { + // const result = await TezosNodeReader.getBlock(tezosServer); - expect(result.header.level).to.be.greaterThan(1); - }); + // expect(result.header.level).to.be.greaterThan(1); + // }); it('Gets delegate for a delegated implicit account', async () => { const result = await TezosNodeReader.getDelegate(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index 975dfb86..2d4aa58d 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -41,26 +41,12 @@ export namespace TezosNodeReader { * Gets the delegate for a smart contract or an implicit account. * * @param {string} server Tezos node to query - * @param {stirng} address The smart contract address or implicit account to query. + * @param {string} accountHash The smart contract address or implicit account to query. + * @returns The address of the delegate, or undefined if there was no delegate set. */ - export async function getDelegate(server: string, address: string): Promise { - const requestUrl = `chains/main/blocks/head/context/contracts/${address}/delegate` - - try { - const delegate = await performGetRequest(server, requestUrl) - // Delegate is a string, even though `performGetRequest` purports to return an object. - return (delegate as unknown) as string - } catch (error) { - const tezosRequestError = error as TezosRequestError - - // Tezos returns a 404 if delegate is not set. - if (tezosRequestError.httpStatus === 404) { - return undefined - } - - // Otherwise, re-throw the error. - throw tezosRequestError - } + export async function getDelegate(server: string, accountHash: string): Promise { + const contractData = await getAccountForBlock(server, 'head', accountHash) + return (contractData.delegate as unknown) as string } /** From e9bbe0e64bc9d43dd1aac0c8aa4760a0dfdeacb7 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 20:27:35 -0700 Subject: [PATCH 52/60] revert tests --- .../chain/tezos/TezosNodeReader.spec.ts | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/integration_test/chain/tezos/TezosNodeReader.spec.ts b/integration_test/chain/tezos/TezosNodeReader.spec.ts index 6433cad0..4c9fcc35 100644 --- a/integration_test/chain/tezos/TezosNodeReader.spec.ts +++ b/integration_test/chain/tezos/TezosNodeReader.spec.ts @@ -10,57 +10,56 @@ import FetchSelector from '../../../src/utils/FetchSelector'; FetchSelector.setFetch(fetch); import { TezosNodeReader } from '../../../src/chain/tezos/TezosNodeReader'; -// import { tezosServer, keys } from '../../TestAssets'; -const tezosServer = "https://rpctest.tzbeta.net" +import { tezosServer, keys } from '../../TestAssets'; describe('TezosNodeReader integration test suite', () => { - // it('Get chain head', async () => { - // const result = await TezosNodeReader.getBlockHead(tezosServer); + it('Get chain head', async () => { + const result = await TezosNodeReader.getBlockHead(tezosServer); - // expect(result['header']['level']).to.be.greaterThan(1); - // }); + expect(result['header']['level']).to.be.greaterThan(1); + }); - // it('Get account counter', async () => { - // const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); + it('Get account counter', async () => { + const result = await TezosNodeReader.getCounterForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.greaterThan(1); - // }); + expect(result).to.be.greaterThan(1); + }); - // it('Get account reveal status', async () => { - // const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); + it('Get account reveal status', async () => { + const result = await TezosNodeReader.isManagerKeyRevealedForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.true; - // }); + expect(result).to.be.true; + }); - // it('Get account manager key', async () => { - // const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); + it('Get account manager key', async () => { + const result = await TezosNodeReader.getAccountManagerForBlock(tezosServer, 'head', keys.publicKeyHash); - // expect(result).to.be.equal(keys.publicKey); - // }); + expect(result).to.be.equal(keys.publicKey); + }); - // it('Get account info', async () => { - // const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); + it('Get account info', async () => { + const result = await TezosNodeReader.getAccountForBlock(tezosServer, 'head', keys.publicKeyHash); - // expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); - // }); + expect(parseInt(result.balance, 10)).to.be.greaterThan(10000); + }); - // it('Get account spendable balance', async () => { - // const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); + it('Get account spendable balance', async () => { + const result = await TezosNodeReader.getSpendableBalanceForAccount(tezosServer, keys.publicKeyHash); - // expect(result).to.be.greaterThan(10000); - // }); + expect(result).to.be.greaterThan(10000); + }); - // it('Get account funding burn flag', async () => { - // const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); + it('Get account funding burn flag', async () => { + const result = await TezosNodeReader.isImplicitAndEmpty(tezosServer, keys.publicKeyHash); - // expect(result).to.be.false; - // }); + expect(result).to.be.false; + }); - // it('Get head', async () => { - // const result = await TezosNodeReader.getBlock(tezosServer); + it('Get head', async () => { + const result = await TezosNodeReader.getBlock(tezosServer); - // expect(result.header.level).to.be.greaterThan(1); - // }); + expect(result.header.level).to.be.greaterThan(1); + }); it('Gets delegate for a delegated implicit account', async () => { const result = await TezosNodeReader.getDelegate(tezosServer, "tz1PnUd6R31MnjEE8VhfZhZdbGc1hrWQvjnK"); From 0040ebf3933ea6aabf52f436c82892a961b17752 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Wed, 9 Dec 2020 20:32:38 -0700 Subject: [PATCH 53/60] fix typo --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index ced889f5..a780fa3d 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -375,7 +375,7 @@ export namespace WrappedTezosHelper { * @param storageLimit The storage limit to use. * @returns A property bag of data about the operation. */ - export async function deplyOven( + export async function deployOven( nodeUrl: string, signer: Signer, keystore: KeyStore, From d8f2308cbc56370aecc53a6d1d82fe75986602b5 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Thu, 10 Dec 2020 23:52:26 -0500 Subject: [PATCH 54/60] - wxtz wrapper update --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 9db58c44..269351cf 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -9,7 +9,6 @@ import { ConseilServerInfo } from '../../../types/conseil/QueryTypes'; import { ContractMapDetailsItem } from '../../../types/conseil/ConseilTezosTypes'; import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; import { StakerDaoTzip7 } from './StakerDaoTzip7'; -import { StakerDAOTokenHelper } from './StakerDAOTokenHelper'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { @@ -108,7 +107,7 @@ const WrappedTezosHelperInternal = { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - depositToOven: async function depositToOven( + depositToOven: async function ( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -197,7 +196,7 @@ const WrappedTezosHelperInternal = { coreContractAddress: string, ovenOwner: string, ovenListBigMapId: number - ): Promise> { + ): Promise { // Fetch map data. const mapData = await TezosConseilClient.getBigMapData(serverInfo, coreContractAddress) if (mapData === undefined) { @@ -235,7 +234,7 @@ const WrappedTezosHelperInternal = { // Map filtered array to only contain oven addresses. return ownedOvens.map((oven: OvenMapSchema) => { return oven.key - }) + }); }, /** @@ -248,12 +247,12 @@ const WrappedTezosHelperInternal = { * @param keystore A Keystore for the sourceAddress. * @param fee The fee to use. * @param coreAddress The address of the core contract. - * @param baker The inital baker for the Oven. If `undefined` the oven will not have an initial baker. Defaults to `undefined`. + * @param baker The initial baker for the Oven. If `undefined` the oven will not have an initial baker. Defaults to `undefined`. * @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 deployOven( + deployOven: async function ( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -441,4 +440,4 @@ export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal & return tokenMatched && wrappedTezosInternalMatched } -} \ No newline at end of file +} From 521ee342dfdc6d185ef46692861cff6fe4beffee Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Fri, 11 Dec 2020 12:28:49 -0700 Subject: [PATCH 55/60] Revert "- wxtz wrapper update" This reverts commit d8f2308cbc56370aecc53a6d1d82fe75986602b5. --- src/chain/tezos/contracts/WrappedTezosHelper.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 269351cf..9db58c44 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -9,6 +9,7 @@ import { ConseilServerInfo } from '../../../types/conseil/QueryTypes'; import { ContractMapDetailsItem } from '../../../types/conseil/ConseilTezosTypes'; import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; import { StakerDaoTzip7 } from './StakerDaoTzip7'; +import { StakerDAOTokenHelper } from './StakerDAOTokenHelper'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { @@ -107,7 +108,7 @@ const WrappedTezosHelperInternal = { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - depositToOven: async function ( + depositToOven: async function depositToOven( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -196,7 +197,7 @@ const WrappedTezosHelperInternal = { coreContractAddress: string, ovenOwner: string, ovenListBigMapId: number - ): Promise { + ): Promise> { // Fetch map data. const mapData = await TezosConseilClient.getBigMapData(serverInfo, coreContractAddress) if (mapData === undefined) { @@ -234,7 +235,7 @@ const WrappedTezosHelperInternal = { // Map filtered array to only contain oven addresses. return ownedOvens.map((oven: OvenMapSchema) => { return oven.key - }); + }) }, /** @@ -247,12 +248,12 @@ const WrappedTezosHelperInternal = { * @param keystore A Keystore for the sourceAddress. * @param fee The fee to use. * @param coreAddress The address of the core contract. - * @param baker The initial baker for the Oven. If `undefined` the oven will not have an initial baker. Defaults to `undefined`. + * @param baker The inital baker for the Oven. If `undefined` the oven will not have an initial baker. Defaults to `undefined`. * @param gasLimit The gas limit to use. * @param storageLimit The storage limit to use. * @returns A property bag of data about the operation. */ - deployOven: async function ( + export async function deployOven( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -440,4 +441,4 @@ export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal & return tokenMatched && wrappedTezosInternalMatched } -} +} \ No newline at end of file From f6e999672d4532aee1fb2e791cbf3fdcc4821e92 Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Fri, 11 Dec 2020 20:44:13 -0700 Subject: [PATCH 56/60] changes --- .../tezos/contracts/WrappedTezosHelper.ts | 240 +++++++++++------- 1 file changed, 149 insertions(+), 91 deletions(-) diff --git a/src/chain/tezos/contracts/WrappedTezosHelper.ts b/src/chain/tezos/contracts/WrappedTezosHelper.ts index 9db58c44..387d4d54 100644 --- a/src/chain/tezos/contracts/WrappedTezosHelper.ts +++ b/src/chain/tezos/contracts/WrappedTezosHelper.ts @@ -1,24 +1,27 @@ +import { JSONPath } from 'jsonpath-plus'; import { KeyStore, Signer } from '../../../types/ExternalInterfaces'; import * as TezosTypes from '../../../types/tezos/TezosChainTypes'; import { TezosMessageUtils } from '../TezosMessageUtil'; +import { TezosNodeReader } from '../TezosNodeReader'; import { TezosNodeWriter } from '../TezosNodeWriter'; import { TezosContractUtils } from './TezosContractUtils'; import { TezosConseilClient } from '../../../reporting/tezos/TezosConseilClient' import { ConseilServerInfo } from '../../../types/conseil/QueryTypes'; import { ContractMapDetailsItem } from '../../../types/conseil/ConseilTezosTypes'; import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes'; -import { StakerDaoTzip7 } from './StakerDaoTzip7'; -import { StakerDAOTokenHelper } from './StakerDAOTokenHelper'; /** The expected checksum for the Wrapped Tezos contracts. */ const CONTRACT_CHECKSUMS = { + token: 'd48b45bd77d2300026fe617c5ba7670e', oven: '5e3c30607da21a0fc30f7be61afb15c7', core: '7b9b5b7e7f0283ff6388eb783e23c452' } /** The expected checksum for the Wrapped Tezos scripts. */ const SCRIPT_CHECKSUMS = { + // TODO(keefertaylor): Compute this checksum correctly. + token: '', // TODO(keefertaylor): Compute this checksum correctly. oven: '', // TODO(keefertaylor): Compute this checksum correctly. @@ -36,6 +39,22 @@ export type OpenOvenResult = { ovenAddress: string } +export interface WrappedTezosStorage { + balanceMap: number; + approvalsMap: number; + supply: number; + administrator: string; + paused: boolean; + pauseGuardian: string; + outcomeMap: number; + swapMap: number; +} + +export interface WrappedTezosBalanceRecord { } +export interface WrappedTezosApprovalRecord { } +export interface WrappedTezosOutcomeRecord { } +export interface WrappedTezosSwapRecord { } + /** * Types for the Oven Map . * @@ -45,11 +64,24 @@ export type OpenOvenResult = { export type OvenMapSchema = { key: string, value: string } /** - * Wrapped Tezos specific functions. + * Interface for the Wrapped XTZ Token and Oven implementation. * - * @see {WrappedTezosHelper} + * @see {@link https://forum.tezosagora.org/t/wrapped-tezos/2195|wXTZ on Tezos Agora} + * + * The token represented by these contracts trades with symbol 'WXTZ' and is specified with 10^-6 precision. Put + * simply, 1 XTZ = 1 WXTZ, and 0.000_001 XTZ = 1 Mutez = 0.000_001 WXTZ. + * + * Canonical Data: + * - Delphinet: + * - Token Contract: KT1JYf7xjCJAqFDfNpuump9woSMaapy1WcMY + * - Core Contract: KT1S98ELFTo6mdMBqhAVbGgKAVgLbdPP3AX8 + * - Token Balances Map ID: 14566 + * - Oven List Map ID: 14569 + * TODO(keefertaylor): Add additional data for mainnet here. + * + * @author Keefer Taylor, Staker Services Ltd */ -const WrappedTezosHelperInternal = { +export namespace WrappedTezosHelper { /** * Verifies that contract code for Wrapped Tezos matches the expected code. * @@ -61,16 +93,18 @@ const WrappedTezosHelperInternal = { * @param coreContractAddress The address of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - verifyDestination: async function ( + export async function verifyDestination( nodeUrl: string, + tokenContractAddress: string, ovenContractAddress: string, coreContractAddress: string ): Promise { - const ovenMatched = await TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven) - const coreMatched = await TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core) + 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 ovenMatched && coreMatched - }, + return tokenMatched && ovenMatched && coreMatched + } /** * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. @@ -82,15 +116,103 @@ const WrappedTezosHelperInternal = { * @param coreScript The script of the core contract. * @returns A boolean indicating if the code was the expected sum. */ - verifyScript: function ( + export function verifyScript( + tokenScript: string, ovenScript: string, coreScript: string ): boolean { + const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token) const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven) const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core) - return ovenMatched && coreMatched - }, + return tokenMatched && ovenMatched && coreMatched + } + + /** + * + * @param server + * @param address + */ + export async function getSimpleStorage(server: string, address: string): Promise { + const storageResult = await TezosNodeReader.getContractStorage(server, address); + + console.log(JSON.stringify(storageResult)); + + return { + balanceMap: Number(JSONPath({ path: '$.args[1].args[0].args[1].args[0].int', json: storageResult })[0]), + approvalsMap: Number(JSONPath({ path: '$.args[1].args[0].args[0].args[1].int', json: storageResult })[0]), + supply: Number(JSONPath({ path: '$.args[1].args[1].args[1].int', json: storageResult })[0]), + administrator: JSONPath({ path: '$.args[1].args[0].args[0].args[0].string', json: storageResult })[0], + paused: (JSONPath({ path: '$.args[1].args[1].args[0].prim', json: storageResult })[0]).toString().toLowerCase().startsWith('t'), + pauseGuardian: JSONPath({ path: '$.args[1].args[0].args[1].args[1].string', json: storageResult })[0], + outcomeMap: Number(JSONPath({ path: '$.args[0].args[0].int', json: storageResult })[0]), + swapMap: Number(JSONPath({ path: '$.args[0].args[1].int', json: storageResult })[0]) + }; + } + + /** + * Get the balance of WXTZ tokens for an address. + * + * @param nodeUrl The URL of the Tezos node which serves data. + * @param mapId The ID of the BigMap which contains balances. + * @param account The account to fetch the token balance for. + * @returns The balance of the account. + */ + export async function getAccountBalance(server: string, mapid: number, account: string): Promise { + const packedKey = TezosMessageUtils.encodeBigMapKey(Buffer.from(TezosMessageUtils.writePackedData(account, 'address'), 'hex')); + const mapResult = await TezosNodeReader.getValueForBigMapKey(server, mapid, packedKey); + + if (mapResult === undefined) { throw new Error(`Map ${mapid} does not contain a record for ${account}`); } + + const numberString = JSONPath({ path: '$.int', json: mapResult }); + return Number(numberString); + } + + /** + * Transfer some WXTZ between addresses. + * + * @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 tokenContractAddress The address of the token contract. + * @param fee The fee to use. + * @param sourceAddress The address which will send tokens. + * @param destinationAddress The address which will receive tokens. + * @param amount The amount of tokens to send. + * @param gasLimit The gas limit to use. + * @param storageLimit The storage limit to use. + * @returns A string representing the operation hash. + */ + export async function transferBalance( + nodeUrl: string, + signer: Signer, + keystore: KeyStore, + tokenContractAddress: string, + fee: number, + sourceAddress: string, + destinationAddress: string, + amount: number, + gasLimit: number = 51_300, + storageLimit: number = 70 + ): Promise { + const parameters = `Pair "${sourceAddress}" (Pair "${destinationAddress}" ${amount})`; + + const nodeResult = await TezosNodeWriter.sendContractInvocationOperation( + nodeUrl, + signer, + keystore, + tokenContractAddress, + 0, + fee, + storageLimit, + gasLimit, + 'transfer', + parameters, + TezosTypes.TezosParameterFormat.Michelson + ); + + return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); + } /** * Deposit XTZ into an oven to mint WXTZ. @@ -108,14 +230,14 @@ const WrappedTezosHelperInternal = { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - depositToOven: async function depositToOven( + export async function depositToOven( nodeUrl: string, signer: Signer, keystore: KeyStore, ovenAddress: string, fee: number, amountMutez: number, - gasLimit: number = 126_500, + gasLimit: number = 150_000, storageLimit: number = 10 ): Promise { const parameters = 'Unit' @@ -135,7 +257,7 @@ const WrappedTezosHelperInternal = { ) return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - }, + } /** * Withdraw XTZ from an oven by repaying WXTZ. @@ -155,7 +277,7 @@ const WrappedTezosHelperInternal = { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - withdrawFromOven: async function ( + export async function withdrawFromOven( nodeUrl: string, signer: Signer, keystore: KeyStore, @@ -182,7 +304,7 @@ const WrappedTezosHelperInternal = { ) return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - }, + } /** * Retrieve a list of all oven addresses a user owns. @@ -192,7 +314,7 @@ const WrappedTezosHelperInternal = { * @param ovenOwner The oven owner to search for * @param ovenListBigMapId The BigMap ID of the oven list. */ - listOven: async function ( + export async function listOvens( serverInfo: ConseilServerInfo, coreContractAddress: string, ovenOwner: string, @@ -236,7 +358,7 @@ const WrappedTezosHelperInternal = { return ownedOvens.map((oven: OvenMapSchema) => { return oven.key }) - }, + } /** * Deploy a new oven contract. @@ -289,7 +411,7 @@ const WrappedTezosHelperInternal = { operationHash, ovenAddress } - }, + } /** * Set the baker for an oven. @@ -306,14 +428,14 @@ const WrappedTezosHelperInternal = { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - setOvenBaker: async function ( + export async function setOvenBaker( nodeUrl: string, signer: Signer, keystore: KeyStore, fee: number, ovenAddress: string, bakerAddress: string, - gasLimit: number = 19_500, + gasLimit: number = 23_500, storageLimit: number = 0, ): Promise { const parameters = `Some "${bakerAddress}"` @@ -333,7 +455,8 @@ const WrappedTezosHelperInternal = { ) return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); - }, + } + /** * Clear the baker for an oven. @@ -349,13 +472,13 @@ const WrappedTezosHelperInternal = { * @param storageLimit The storage limit to use. * @returns A string representing the operation hash. */ - clearOvenBaker: async function ( + export async function clearOvenBaker( nodeUrl: string, signer: Signer, keystore: KeyStore, fee: number, ovenAddress: string, - gasLimit: number = 19_500, + gasLimit: number = 23_500, storageLimit: number = 0, ): Promise { const parameters = `None` @@ -376,69 +499,4 @@ const WrappedTezosHelperInternal = { return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID); } -} - -/** - * Interface for the Wrapped XTZ Token and Oven implementation. - * - * @see {@link https://forum.tezosagora.org/t/wrapped-tezos/2195|wXTZ on Tezos Agora} - * - * The token represented by these contracts trades with symbol 'WXTZ' and is specified with 10^-6 precision. Put - * simply, 1 XTZ = 1 WXTZ, and 0.000_001 XTZ = 1 Mutez = 0.000_001 WXTZ. - * - * Canonical Data: - * - Delphinet: - * - Token Contract: KT1JYf7xjCJAqFDfNpuump9woSMaapy1WcMY - * - Core Contract: KT1S98ELFTo6mdMBqhAVbGgKAVgLbdPP3AX8 - * - Token Balances Map ID: 14566 - * - Oven List Map ID: 14569 - * TODO(keefertaylor): Add additional data for mainnet here. - * - * @author Keefer Taylor, Staker Services Ltd - */ -export const WrappedTezosHelper = StakerDaoTzip7 && WrappedTezosHelperInternal && { - /** - * Verifies that contract code for Wrapped Tezos matches the expected code. - * - * Note: This function processes contracts in the Micheline format. - * - * @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. - */ - verifyDestination: async function verifyDestination( - nodeUrl: string, - tokenContractAddress: string, - ovenContractAddress: string, - coreContractAddress: string - ): Promise { - const tokenMatched = await StakerDaoTzip7.verifyDestination(nodeUrl, tokenContractAddress) - const wrappedTezosInternalMatched = await WrappedTezosHelperInternal.verifyDestination(nodeUrl, ovenContractAddress, coreContractAddress) - - return tokenMatched && wrappedTezosInternalMatched - }, - - /** - * Verifies that Michelson script for Wrapped Tezos contracts matches the expected code. - * - * Note: This function processes scrips in Michelson format. - * - * @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. - */ - verifyScript: function ( - tokenScript: string, - ovenScript: string, - coreScript: string - ): boolean { - // Confirm that both interfaces report contracts correctly. - const tokenMatched = StakerDaoTzip7.verifyScript(tokenScript) - const wrappedTezosInternalMatched = WrappedTezosHelperInternal.verifyScript(ovenScript, coreScript) - - return tokenMatched && wrappedTezosInternalMatched - } } \ No newline at end of file From d07b3661bdd3753a6e8395f4b9fe010cd5c2981a Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Fri, 11 Dec 2020 23:13:28 -0700 Subject: [PATCH 57/60] stakerdao mvp --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d6d085f1..112b1709 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "conseiljs", + "name": "@tessellatedgeometry/conseiljs", "version": "5.0.6", "description": "Client-side library for Tezos dApp development.", "browser": "dist/index-web.js", @@ -172,4 +172,4 @@ "timeout": 20000, "bail": false } -} +} \ No newline at end of file From a02e0e5d2f414445af3892c053376808fbcb6ab1 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Sat, 12 Dec 2020 02:52:03 -0500 Subject: [PATCH 58/60] - truncate block hash recieved from the node (SECURITY) --- src/chain/tezos/TezosNodeWriter.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/chain/tezos/TezosNodeWriter.ts b/src/chain/tezos/TezosNodeWriter.ts index d911f880..e3b22920 100644 --- a/src/chain/tezos/TezosNodeWriter.ts +++ b/src/chain/tezos/TezosNodeWriter.ts @@ -170,14 +170,16 @@ export namespace TezosNodeWriter { */ export async function sendOperation(server: string, operations: TezosP2PMessageTypes.Operation[], signer: Signer, offset: number = 54): Promise { const blockHead = await TezosNodeReader.getBlockAtOffset(server, offset); - const forgedOperationGroup = forgeOperations(blockHead.hash, operations); + const blockHash = blockHead.hash.slice(0, 51); // consider throwing an error instead + + const forgedOperationGroup = forgeOperations(blockHash, operations); const opSignature = await signer.signOperation(Buffer.from(TezosConstants.OperationGroupWatermark + forgedOperationGroup, 'hex')); const signedOpGroup = Buffer.concat([Buffer.from(forgedOperationGroup, 'hex'), opSignature]); const base58signature = TezosMessageUtils.readSignatureWithHint(opSignature, signer.getSignerCurve()); const opPair = { bytes: signedOpGroup, signature: base58signature }; - const appliedOp = await preapplyOperation(server, blockHead.hash, blockHead.protocol, operations, opPair); + const appliedOp = await preapplyOperation(server, blockHash, blockHead.protocol, operations, opPair); const injectedOperation = await injectOperation(server, opPair); return { results: appliedOp[0], operationGroupID: injectedOperation }; // TODO From cbdf25b80f3587e719f7e3079d107b759e43250a Mon Sep 17 00:00:00 2001 From: Keefer Taylor Date: Sun, 13 Dec 2020 22:15:50 -0800 Subject: [PATCH 59/60] Update package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 112b1709..d6d085f1 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@tessellatedgeometry/conseiljs", + "name": "conseiljs", "version": "5.0.6", "description": "Client-side library for Tezos dApp development.", "browser": "dist/index-web.js", @@ -172,4 +172,4 @@ "timeout": 20000, "bail": false } -} \ No newline at end of file +} From 7aeca0960dc39d370375ffa4bca8ab126cfe6192 Mon Sep 17 00:00:00 2001 From: anonymoussprocket Date: Mon, 14 Dec 2020 12:56:16 -0500 Subject: [PATCH 60/60] - correct delegate type --- src/chain/tezos/TezosNodeReader.ts | 2 +- src/types/tezos/TezosRPCResponseTypes.ts | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/chain/tezos/TezosNodeReader.ts b/src/chain/tezos/TezosNodeReader.ts index 2d4aa58d..140d5c9e 100644 --- a/src/chain/tezos/TezosNodeReader.ts +++ b/src/chain/tezos/TezosNodeReader.ts @@ -46,7 +46,7 @@ export namespace TezosNodeReader { */ export async function getDelegate(server: string, accountHash: string): Promise { const contractData = await getAccountForBlock(server, 'head', accountHash) - return (contractData.delegate as unknown) as string + return contractData.delegate; } /** diff --git a/src/types/tezos/TezosRPCResponseTypes.ts b/src/types/tezos/TezosRPCResponseTypes.ts index 9e01872a..f0a82b58 100644 --- a/src/types/tezos/TezosRPCResponseTypes.ts +++ b/src/types/tezos/TezosRPCResponseTypes.ts @@ -122,12 +122,7 @@ export interface TezosBlockOperationContentMetadataOperationResult { */ export interface Contract { balance: string; - delegate?: ContractDelegate; + delegate?: string; script?: any; counter: string; } - -export interface ContractDelegate { - setable: boolean, - value: string -}