From ddeb5cd4af2c6f9b81cf19505aad34b4240af803 Mon Sep 17 00:00:00 2001 From: Timur Ramazanov Date: Thu, 18 Jun 2020 17:28:56 +0300 Subject: [PATCH] Protocol 13 support (#193) --- package.json | 2 +- src/init/graphql_server.ts | 5 +-- src/init/ingestd.ts | 5 +-- src/init/stellar.ts | 15 --------- .../factories/transaction_with_xdr_factory.ts | 31 ++++++++++--------- src/repo/transactions.ts | 21 +------------ src/schema/resolvers/account.ts | 5 ++- src/schema/resolvers/ledger.ts | 2 +- src/storage/base.ts | 2 +- src/storage/connection.ts | 2 +- src/storage/connection_pool.ts | 3 +- src/util/logger.ts | 10 ++---- tests/integration/integration.test.ts | 3 -- tests/unit/ingest/cursor.test.ts | 4 +-- yarn.lock | 21 +++++++++---- 15 files changed, 46 insertions(+), 85 deletions(-) diff --git a/package.json b/package.json index 4599ecea..b814ee30 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "progress": "^2.0.3", "retry": "^0.12.0", "squel": "^5.12.2", - "stellar-base": "^2.1.0", + "stellar-base": "^3.0.3", "typeorm": "^0.2.17", "typescript-memoize": "^1.0.0-alpha.3", "winston": "^3.0.0" diff --git a/src/init/graphql_server.ts b/src/init/graphql_server.ts index c1699ce3..ae85138c 100644 --- a/src/init/graphql_server.ts +++ b/src/init/graphql_server.ts @@ -7,16 +7,13 @@ import logger from "../util/logger"; import "../util/memo"; import { initDatabase } from "./db"; import { initSentry } from "./sentry"; -import { setStellarNetwork, updateBaseReserve } from "./stellar"; +import { updateBaseReserve } from "./stellar"; export async function initGraphqlServer() { logger.info("Initializing..."); logger.info("Sentry..."); return initSentry() - .then(() => logger.info("Setting Stellar network...")) - .then(setStellarNetwork) - .then(network => logger.info(`Astrograph will use the network with passphrase "${network}"`)) .then(() => logger.info("Connecting to the database...")) .then(initDatabase) .then(() => logger.info("Creating connection for pubsub...")) diff --git a/src/init/ingestd.ts b/src/init/ingestd.ts index 4670736f..f277d600 100644 --- a/src/init/ingestd.ts +++ b/src/init/ingestd.ts @@ -6,20 +6,17 @@ import logger from "../util/logger"; import { STELLAR_CORE_CURSOR_NAME } from "../util/secrets"; import { initDatabase } from "./db"; import { initSentry } from "./sentry"; -import { setStellarNetwork } from "./stellar"; export async function initIngestd() { logger.info("Initializing..."); logger.info("Sentry..."); return initSentry() - .then(() => logger.info("Setting Stellar network...")) - .then(setStellarNetwork) .then(network => logger.info(`Astrograph will use ${network}`)) .then(() => logger.info("Connecting to the database...")) .then(initDatabase) .catch((e: Error) => { - console.error(`Failed to connect to the database: ${e.message}`); + logger.error(`Failed to connect to the database: ${e.message}`); process.exit(1); }) .then(() => logger.info("Setting cursor...")) diff --git a/src/init/stellar.ts b/src/init/stellar.ts index 5bd956df..51d4157e 100644 --- a/src/init/stellar.ts +++ b/src/init/stellar.ts @@ -1,20 +1,5 @@ -import { Network } from "stellar-base"; import { db } from "../database"; import { setBaseReserve } from "../util/base_reserve"; -import { STELLAR_NETWORK } from "../util/secrets"; - -export function setStellarNetwork(): Promise { - if (STELLAR_NETWORK === "pubnet") { - Network.usePublicNetwork(); - } else if (STELLAR_NETWORK === "testnet") { - Network.useTestNetwork(); - } else { - const network = new Network(STELLAR_NETWORK); - Network.use(network); - } - - return Promise.resolve(Network.current().networkPassphrase()); -} export async function updateBaseReserve(): Promise { const lastLedgerHeader = await db.ledgerHeaders.getLastLedgerHeader(); diff --git a/src/model/factories/transaction_with_xdr_factory.ts b/src/model/factories/transaction_with_xdr_factory.ts index 533025ca..95baa495 100644 --- a/src/model/factories/transaction_with_xdr_factory.ts +++ b/src/model/factories/transaction_with_xdr_factory.ts @@ -1,6 +1,5 @@ import stellar from "stellar-base"; import { ITransactionData as IStorageTransactionData } from "../../storage/types"; -import { publicKeyFromBuffer } from "../../util/xdr"; import { ITimeBounds, Transaction } from "../transaction"; import { ITransactionWithXDR, TransactionWithXDR } from "../transaction_with_xdr"; @@ -17,44 +16,48 @@ export interface ITransactionTableRow { // NOTE: Might use some instantiation from static method here export class TransactionWithXDRFactory { public static fromDb(row: ITransactionTableRow): TransactionWithXDR { - const bodyXDR = stellar.xdr.TransactionEnvelope.fromXDR(row.txbody, "base64"); const resultXDR = stellar.xdr.TransactionResultPair.fromXDR(row.txresult, "base64"); const metaXDR = stellar.xdr.TransactionMeta.fromXDR(row.txmeta, "base64"); const feeMetaXDR = stellar.xdr.OperationMeta.fromXDR(row.txfeemeta, "base64"); - const body = bodyXDR.tx(); - const result = resultXDR.result(); - - const memo = stellar.Memo.fromXDRObject(body.memo()); + const tx = new stellar.Transaction(row.txbody, stellar.Networks.TESTNET); - const timeBounds = this.parseTimeBounds(body.timeBounds()); + const result = resultXDR.result(); const resultCode = result.result().switch().value; const success = resultCode === stellar.xdr.TransactionResultCode.txSuccess().value; - const feeAmount = body.fee().toString(); const feeCharged = result.feeCharged().toString(); - const sourceAccount = publicKeyFromBuffer(body.sourceAccount().value()); + + let timeBounds: ITimeBounds | undefined; + + if (tx.timeBounds) { + timeBounds = { minTime: new Date(tx.timeBounds.minTime * 1000) }; + + if (tx.timeBounds.maxTime !== "0") { + timeBounds.maxTime = new Date(tx.timeBounds.maxTime * 1000); + } + } const data: ITransactionWithXDR = { id: row.txid, index: row.txindex, ledgerSeq: row.ledgerseq, body: row.txbody, - bodyXDR, + bodyXDR: tx.tx, result: row.txresult, resultXDR, meta: row.txmeta, metaXDR, feeMeta: row.txfeemeta, feeMetaXDR, - memo: memo.value ? memo : undefined, + memo: tx.memo.value ? tx.memo : undefined, timeBounds, - feeAmount, + feeAmount: tx.fee, feeCharged, resultCode, success, - sourceAccount, - operationsXDR: body.operations(), + sourceAccount: tx.source, + operationsXDR: tx.operations, operationResultsXDR: result.result().results() }; diff --git a/src/repo/transactions.ts b/src/repo/transactions.ts index 7257ab9b..fa083176 100644 --- a/src/repo/transactions.ts +++ b/src/repo/transactions.ts @@ -1,6 +1,6 @@ import { IDatabase } from "pg-promise"; import { TransactionWithXDR } from "../model"; -import { ITransactionTableRow, TransactionWithXDRFactory } from "../model/factories"; +import { TransactionWithXDRFactory } from "../model/factories"; const sql = { selectTx: @@ -18,25 +18,6 @@ export default class TransactionsRepo { this.db = db; } - // Tries to find a transaction by id; - public findByID(id: string): Promise { - return this.db.oneOrNone(sql.selectTx, id, (res: ITransactionTableRow) => - res ? TransactionWithXDRFactory.fromDb(res) : null - ); - } - - // TODO: Must be DRYed - public async findAllByID(ids: string[]): Promise> { - if (ids.length === 0) { - return new Array(); - } - - const res = await this.db.manyOrNone(sql.selectTxIn, [ids]); - const txs = res.map((v: ITransactionTableRow) => TransactionWithXDRFactory.fromDb(v)); - - return ids.map(id => txs.find(a => a.id === id) || null); - } - // Fetches all transactions by ledger seq; public async findAllBySeq(seq: number): Promise { const txs = await this.db.manyOrNone(sql.selectTxNoFee, seq); diff --git a/src/schema/resolvers/account.ts b/src/schema/resolvers/account.ts index d4e71ccc..9631ddf1 100644 --- a/src/schema/resolvers/account.ts +++ b/src/schema/resolvers/account.ts @@ -75,9 +75,8 @@ export default { storage.filterTypes(type); } - return makeConnection( - await storage.forAccount(root.id).all(paging), - r => OperationFactory.fromStorage(r), + return makeConnection(await storage.forAccount(root.id).all(paging), r => + OperationFactory.fromStorage(r) ); }, payments: async (root: Account, args: any, ctx: IApolloContext) => { diff --git a/src/schema/resolvers/ledger.ts b/src/schema/resolvers/ledger.ts index 085243c9..7afdde93 100644 --- a/src/schema/resolvers/ledger.ts +++ b/src/schema/resolvers/ledger.ts @@ -14,7 +14,7 @@ const ledgerHeaderResolver = createBatchResolver(async (le const seqNumsWithoutHeaders = ledgers.filter(l => l.header === undefined).map(l => l.seq); let fetchedHeaders: LedgerHeaderModel[] = []; - if (seqNumsWithoutHeaders.length != 0) { + if (seqNumsWithoutHeaders.length !== 0) { fetchedHeaders = (await getRepository(LedgerHeader).find({ where: { seq: In(seqNumsWithoutHeaders) } })).map(h => LedgerHeaderFactory.fromXDR(h.data) ); diff --git a/src/storage/base.ts b/src/storage/base.ts index b554f9ea..1b4f1571 100644 --- a/src/storage/base.ts +++ b/src/storage/base.ts @@ -34,7 +34,7 @@ export abstract class BaseStorage { } }; - return (pagingParams ? properlyOrdered(docs, pagingParams) : docs); + return pagingParams ? properlyOrdered(docs, pagingParams) : docs; } // Finds document by ElasticSearch id diff --git a/src/storage/connection.ts b/src/storage/connection.ts index 6f700cc3..4061f93d 100644 --- a/src/storage/connection.ts +++ b/src/storage/connection.ts @@ -3,4 +3,4 @@ import * as secrets from "../util/secrets"; const connection = new ElasticClient({ node: secrets.ELASTIC_URL }); -export { connection } +export { connection }; diff --git a/src/storage/connection_pool.ts b/src/storage/connection_pool.ts index 4f2cbe9f..bc1b2155 100644 --- a/src/storage/connection_pool.ts +++ b/src/storage/connection_pool.ts @@ -1,4 +1,3 @@ import { ConnectionPool as ElasticConnectionPool } from "@elastic/elasticsearch"; -export class ConnectionPool extends ElasticConnectionPool { -} +export class ConnectionPool extends ElasticConnectionPool {} diff --git a/src/util/logger.ts b/src/util/logger.ts index 8c5531e4..490f37a2 100644 --- a/src/util/logger.ts +++ b/src/util/logger.ts @@ -20,19 +20,13 @@ if (!logLevel || !LoggerLevel[logLevel]) { logLevel = process.env.NODE_ENV === "production" ? PROD_LOG_LEVEL : DEV_LOG_LEVEL; } -const logFormat = printf((info) => { +const logFormat = printf(info => { const stacktrace = info.stack ? `\n${info.stack}` : ""; return `${info.timestamp} ${info.level}: ${info.message}${stacktrace}`; }); const logger = createLogger({ - format: combine( - errors({ stack: true }), - colorize(), - splat(), - timestamp(), - logFormat, - ), + format: combine(errors({ stack: true }), colorize(), splat(), timestamp(), logFormat), transports: [ new transports.Console({ level: logLevel }), new transports.File({ filename: "error.log", level: LOG_FILE }) diff --git a/tests/integration/integration.test.ts b/tests/integration/integration.test.ts index b9fcc41f..c2cfa344 100644 --- a/tests/integration/integration.test.ts +++ b/tests/integration/integration.test.ts @@ -4,15 +4,12 @@ import { execSync } from "child_process"; import fs from "fs"; import path from "path"; import { Client as pgClient } from "pg"; -import { Network } from "stellar-base"; import { createConnection, getConnection } from "typeorm"; import { Account, AccountData, Asset, LedgerHeader, Offer, TrustLine } from "../../src/orm/entities"; import schema from "../../src/schema"; import logger from "../../src/util/logger"; import { DATABASE_URL } from "../../src/util/secrets"; -Network.useTestNetwork(); - const server = new ApolloServer({ schema }); const queryServer = createTestClient(server).query; diff --git a/tests/unit/ingest/cursor.test.ts b/tests/unit/ingest/cursor.test.ts index 0730fb4c..54270878 100644 --- a/tests/unit/ingest/cursor.test.ts +++ b/tests/unit/ingest/cursor.test.ts @@ -1,8 +1,8 @@ -import typeorm = require('typeorm'); -import { LedgersStorage } from "../../../src/storage/ledgers"; +import typeorm = require("typeorm"); import { Cursor } from "../../../src/ingest/cursor"; import { LedgerHeader } from "../../../src/model"; import { LedgerHeaderFactory } from "../../../src/model/factories"; +import { LedgersStorage } from "../../../src/storage/ledgers"; let subject: Cursor; let currentSeq: number; diff --git a/yarn.lock b/yarn.lock index baec1638..ffefa5df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3863,7 +3863,7 @@ jest@^24.7.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-xdr@^1.1.0, js-xdr@^1.1.1: +js-xdr@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/js-xdr/-/js-xdr-1.1.2.tgz#aba1f0952508c83f33dd7e774fa9231b3073992b" integrity sha512-ipiz1CnsyjLsba+QQd5jezGXddNKGa4oO9EODy0kWr3G3R8MNslIxkhQFpyRfY3yoY7YplhRVfC3cmXb4AobZQ== @@ -3873,6 +3873,15 @@ js-xdr@^1.1.0, js-xdr@^1.1.1: lodash "^4.17.5" long "^2.2.3" +js-xdr@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/js-xdr/-/js-xdr-1.1.4.tgz#678df4c6f8c7960de85bdf3bfa02b89df2730777" + integrity sha512-Xhwys9hyDZQDisxCKZi2nDhvGg6fKhsEgAUaJlzjwo32mZ2gZVIQl3+w4Le5SX5dsKDsboFdM2gnu5JALWetTg== + dependencies: + cursor "^0.1.5" + lodash "^4.17.5" + long "^2.2.3" + js-yaml@3.13.1, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" @@ -5713,15 +5722,15 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -stellar-base@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-2.1.0.tgz#27c1951920f8013b6dde74f29427a7e9ce9d16d8" - integrity sha512-Q+N+H3ch5JHqnTyMyKYVwRMFQSJjno5jvM+zQkr+On1Gwihe0s/T5hNMBfMrpdj4BVt9muVAYm8OpWPVTwq6rQ== +stellar-base@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-3.0.3.tgz#e4b033d113f11e9239ce4fe8ead6e9a791f04f14" + integrity sha512-Kb79uQOmlMhGw96rg5qRA+rxK58N2eH+q8OuqVgQr85t5l/+p35BFKVl2yW3xN/OVwY7NrAjFn/KJmoxjcTfeg== dependencies: base32.js "^0.1.0" bignumber.js "^4.0.0" crc "^3.5.0" - js-xdr "^1.1.1" + js-xdr "^1.1.3" lodash "^4.17.11" sha.js "^2.3.6" tweetnacl "^1.0.0"