var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
    var m = o[Symbol.asyncIterator], i;
    return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
import { request } from 'graphql-request';
import gql from 'graphql-tag';
import { dateToNumber, numberToDate } from '../../../../utils/date';
import { TRANSACTIONS_BATCH_LIMIT, CYBERLINKS_BATCH_LIMIT } from './consts';
import { fetchIterable } from './utils/fetch';
import { serializeError } from 'serialize-error';
const messagesByAddress = gql(`
  query MyQuery($address: _text, $limit: bigint, $offset: bigint, $timestamp_from: timestamp) {
  messages_by_address(
    args: {addresses: $address, limit: $limit, offset: $offset, types: "{}"},
    order_by: {transaction: {block: {timestamp: desc}}},
    where: {transaction: {block: {timestamp: {_gt: $timestamp_from}}}}
    ) {
    transaction_hash
    value
    transaction {
      memo
      success
      block {
        timestamp,
        height
      }
    }
    type
  }
}
`);
const cyberlinksByParticle = gql(`
query Cyberlinks($limit: Int, $offset: Int, $orderBy: [cyberlinks_order_by!], $where: cyberlinks_bool_exp) {
  cyberlinks(limit: $limit, offset: $offset, order_by: $orderBy, where: $where) {
    from: particle_from
    to: particle_to
    timestamp
    neuron
  }
}
`);
const cyberlinksSyncStats = gql(`
  query Cyberlinks($where: cyberlinks_bool_exp) {
    cyberlinks_aggregate(where: $where) {
      aggregate {
        count
      }
    }
    first: cyberlinks(limit: 1, order_by: { timestamp: asc }, where: $where) {
      timestamp
    }
    last: cyberlinks(limit: 1, order_by: { timestamp: desc }, where: $where) {
      timestamp,
      to: particle_to,
      from: particle_from
    }
  }
`);
const fetchTransactions = (cyberIndexUrl, address, timestampFrom, offset = 0) => __awaiter(void 0, void 0, void 0, function* () {
    try {
        const res = yield request(cyberIndexUrl, messagesByAddress, {
            address: `{${address}}`,
            limit: TRANSACTIONS_BATCH_LIMIT,
            timestamp_from: numberToDate(timestampFrom),
            offset,
        });
        return res === null || res === void 0 ? void 0 : res.messages_by_address;
    }
    catch (e) {
        const serializedError = serializeError(e);
        console.log('--- fetchTransactions:', JSON.stringify(serializedError, null, 2));
        return [];
    }
});
const fetchCyberlinks = (cyberIndexUrl, particleCid, timestampFrom, offset = 0) => __awaiter(void 0, void 0, void 0, function* () {
    try {
        const res = yield request(cyberIndexUrl, cyberlinksByParticle, {
            limit: CYBERLINKS_BATCH_LIMIT,
            offset,
            orderBy: [
                {
                    timestamp: 'desc',
                },
            ],
            where: {
                _or: [
                    {
                        particle_to: {
                            _eq: particleCid,
                        },
                    },
                    {
                        particle_from: {
                            _eq: particleCid,
                        },
                    },
                ],
                timestamp: {
                    _gt: numberToDate(timestampFrom),
                },
            },
        });
        return res.cyberlinks;
    }
    catch (e) {
        const serializedError = serializeError(e);
        console.log('--- fetchCyberlinks:', JSON.stringify(serializedError, null, 2));
        return [];
    }
});
export function fetchAllCyberlinks(cyberIndexUrl, cid, timestampFrom = 0) {
    var _a, e_1, _b, _c;
    return __awaiter(this, void 0, void 0, function* () {
        const cyberlinsIterable = fetchCyberlinksIterable(cyberIndexUrl, cid, timestampFrom);
        const links = [];
        try {
            for (var _d = true, cyberlinsIterable_1 = __asyncValues(cyberlinsIterable), cyberlinsIterable_1_1; cyberlinsIterable_1_1 = yield cyberlinsIterable_1.next(), _a = cyberlinsIterable_1_1.done, !_a;) {
                _c = cyberlinsIterable_1_1.value;
                _d = false;
                try {
                    const batch = _c;
                    links.push(...batch);
                }
                finally {
                    _d = true;
                }
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (!_d && !_a && (_b = cyberlinsIterable_1.return)) yield _b.call(cyberlinsIterable_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        return links;
    });
}
const fetchTransactionsIterable = (cyberIndexUrl, neuronAddress, timestamp) => fetchIterable(fetchTransactions, cyberIndexUrl, neuronAddress, timestamp);
const fetchCyberlinksIterable = (cyberIndexUrl, particleCid, timestamp) => fetchIterable(fetchCyberlinks, cyberIndexUrl, particleCid, timestamp);
const fetchCyberlinkSyncStats = (cyberIndexUrl, particleCid, timestampFrom) => __awaiter(void 0, void 0, void 0, function* () {
    const res = yield request(cyberIndexUrl, cyberlinksSyncStats, {
        where: {
            _or: [
                {
                    particle_to: {
                        _eq: particleCid,
                    },
                },
                {
                    particle_from: {
                        _eq: particleCid,
                    },
                },
            ],
            timestamp: {
                _gt: numberToDate(timestampFrom),
            },
        },
    });
    const { first, last, cyberlinks_aggregate: { aggregate: { count }, }, } = res;
    const lastCyberlink = last[0];
    if (!lastCyberlink) {
        return undefined;
    }
    const isFrom = (lastCyberlink === null || lastCyberlink === void 0 ? void 0 : lastCyberlink.from) === particleCid;
    const lastLinkedParticle = lastCyberlink &&
        (lastCyberlink.from === particleCid
            ? lastCyberlink.to
            : lastCyberlink.from);
    return {
        firstTimestamp: first.length > 0 ? dateToNumber(first[0].timestamp) : 0,
        lastTimestamp: lastCyberlink ? dateToNumber(lastCyberlink.timestamp) : 0,
        lastLinkedParticle,
        isFrom,
        count,
    };
});
export { fetchTransactionsIterable, fetchTransactions, fetchCyberlinksIterable, fetchCyberlinkSyncStats, };
//# sourceMappingURL=requests.js.map