@cityofzion/bs-ethereum 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ {
2
+ "files": {
3
+ "packages/bs-ethereum/jest.config.ts": "d944475db93cbe41a9339187fd94b9962e411c43",
4
+ "packages/bs-ethereum/jest.setup.ts": "9a1976a32050616d4d2ee95b1aa21041bc4daca3",
5
+ "packages/bs-ethereum/package.json": "00abfb87cbc8ce01504511abff875edec226e059",
6
+ "packages/bs-ethereum/src/BSEthereum.ts": "ea8070202977445b77ff67135f7fc7093f0ed2b9",
7
+ "packages/bs-ethereum/src/BitqueryBDSEthereum.ts": "08abbfa7b39f842b722cf58953bfb1e73745fcc9",
8
+ "packages/bs-ethereum/src/BitqueryEDSEthereum.ts": "c04aa2be223166140f3b98e01390a6f5f7ded8df",
9
+ "packages/bs-ethereum/src/GhostMarketNDSEthereum.ts": "145273284b3c27494eea0e80c0c1de8001b11c57",
10
+ "packages/bs-ethereum/src/RpcBDSEthereum.ts": "d5e1ec436231894672fee3e677a8dc2f56628b0e",
11
+ "packages/bs-ethereum/src/__tests__/BDSEthereum.spec.ts": "8b66ba80d8457601fac69819cc1fae4d7bc7b08a",
12
+ "packages/bs-ethereum/src/__tests__/BSEthereum.spec.ts": "0da33cb4c9f89a3b6c2c8445d800ff4ddb41d161",
13
+ "packages/bs-ethereum/src/__tests__/BitqueryEDSEthereum.spec.ts": "8e26084a00916be48eeeb65d3918e5eed6368f0c",
14
+ "packages/bs-ethereum/src/__tests__/GhostMarketNDSEthereum.spec.ts": "f5c9ba8f6c866b97bcf647d105bfa2d5f140180d",
15
+ "packages/bs-ethereum/src/assets/tokens/common.json": "4dbbf3a3b38422e743cf631ffb6c39231777b88d",
16
+ "packages/bs-ethereum/src/constants.ts": "40862a7cc04298a21e380ecdf02e09349897a6f5",
17
+ "packages/bs-ethereum/src/graphql.ts": "aadff73a44a9d12cc65ebe1b0b161f1ecc4f6021",
18
+ "packages/bs-ethereum/src/index.ts": "69ca9c23acdd0afd70f7eaa0a840b07b62bdb07a",
19
+ "packages/bs-ethereum/tsconfig.build.json": "4dc23fb9c4c5e4d19a9bc3947a47c523f4bd967c",
20
+ "packages/bs-ethereum/tsconfig.json": "93e09769572b58e642d4990e9552c70a8b85e142",
21
+ "common/config/rush/npm-shrinkwrap.json": "c7f58d681afa54f5c08d809a1ace9947b56fb633"
22
+ },
23
+ "arguments": "tsc --project tsconfig.build.json "
24
+ }
@@ -0,0 +1,2 @@
1
+ Invoking: tsc --project tsconfig.build.json
2
+
@@ -0,0 +1,23 @@
1
+ import { Account, AccountWithDerivationPath, BSCalculableFee, BSWithNameService, BSWithNft, BlockchainDataService, BlockchainService, ExchangeDataService, Network, NftDataService, PartialBy, Token, TransferParam } from '@cityofzion/blockchain-service';
2
+ export declare class BSEthereum<BSCustomName extends string = string> implements BlockchainService, BSWithNft, BSWithNameService, BSCalculableFee {
3
+ readonly blockchainName: BSCustomName;
4
+ readonly feeToken: Token;
5
+ readonly derivationPath: string;
6
+ blockchainDataService: BlockchainDataService;
7
+ exchangeDataService: ExchangeDataService;
8
+ tokens: Token[];
9
+ nftDataService: NftDataService;
10
+ network: Network;
11
+ constructor(blockchainName: BSCustomName, network: PartialBy<Network, 'url'>);
12
+ setNetwork(param: PartialBy<Network, 'url'>): void;
13
+ validateAddress(address: string): boolean;
14
+ validateEncrypted(json: string): boolean;
15
+ validateKey(key: string): boolean;
16
+ validateNameServiceDomainFormat(domainName: string): boolean;
17
+ generateAccountFromMnemonic(mnemonic: string[] | string, index: number): AccountWithDerivationPath;
18
+ generateAccountFromKey(key: string): Account;
19
+ decrypt(json: string, password: string): Promise<Account>;
20
+ transfer({ senderAccount, intent }: TransferParam): Promise<string>;
21
+ calculateTransferFee({ senderAccount, intent }: TransferParam, details?: boolean | undefined): Promise<string>;
22
+ resolveNameServiceDomain(domainName: string): Promise<string>;
23
+ }
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.BSEthereum = void 0;
36
+ const ethers_1 = require("ethers");
37
+ const ethersJsonWallets = __importStar(require("@ethersproject/json-wallets"));
38
+ const ethersBytes = __importStar(require("@ethersproject/bytes"));
39
+ const ethersBigNumber = __importStar(require("@ethersproject/bignumber"));
40
+ const constants_1 = require("./constants");
41
+ const BitqueryEDSEthereum_1 = require("./BitqueryEDSEthereum");
42
+ const GhostMarketNDSEthereum_1 = require("./GhostMarketNDSEthereum");
43
+ const RpcBDSEthereum_1 = require("./RpcBDSEthereum");
44
+ const BitqueryBDSEthereum_1 = require("./BitqueryBDSEthereum");
45
+ class BSEthereum {
46
+ constructor(blockchainName, network) {
47
+ this.blockchainName = blockchainName;
48
+ this.derivationPath = constants_1.DERIVATION_PATH;
49
+ this.tokens = constants_1.TOKENS[network.type];
50
+ this.feeToken = this.tokens.find(token => token.symbol === 'ETH');
51
+ this.setNetwork(network);
52
+ }
53
+ setNetwork(param) {
54
+ var _a;
55
+ const network = {
56
+ type: param.type,
57
+ url: (_a = param.url) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_URL_BY_NETWORK_TYPE[param.type],
58
+ };
59
+ this.network = network;
60
+ if (network.type === 'custom') {
61
+ this.blockchainDataService = new RpcBDSEthereum_1.RpcBDSEthereum(network);
62
+ }
63
+ else {
64
+ this.blockchainDataService = new BitqueryBDSEthereum_1.BitqueryBDSEthereum(network);
65
+ }
66
+ this.exchangeDataService = new BitqueryEDSEthereum_1.BitqueryEDSEthereum(network.type);
67
+ this.nftDataService = new GhostMarketNDSEthereum_1.GhostMarketNDSEthereum(network.type);
68
+ }
69
+ validateAddress(address) {
70
+ return ethers_1.ethers.utils.isAddress(address);
71
+ }
72
+ validateEncrypted(json) {
73
+ return ethersJsonWallets.isCrowdsaleWallet(json) || ethersJsonWallets.isKeystoreWallet(json);
74
+ }
75
+ validateKey(key) {
76
+ try {
77
+ if (!key.startsWith('0x')) {
78
+ key = '0x' + key;
79
+ }
80
+ if (ethersBytes.hexDataLength(key) !== 32)
81
+ return false;
82
+ return true;
83
+ }
84
+ catch (error) {
85
+ return false;
86
+ }
87
+ }
88
+ validateNameServiceDomainFormat(domainName) {
89
+ if (!domainName.endsWith('.eth'))
90
+ return false;
91
+ return true;
92
+ }
93
+ generateAccountFromMnemonic(mnemonic, index) {
94
+ const path = this.derivationPath.replace('?', index.toString());
95
+ const wallet = ethers_1.ethers.Wallet.fromMnemonic(Array.isArray(mnemonic) ? mnemonic.join(' ') : mnemonic, path);
96
+ return {
97
+ address: wallet.address,
98
+ key: wallet.privateKey,
99
+ type: 'privateKey',
100
+ derivationPath: path,
101
+ };
102
+ }
103
+ generateAccountFromKey(key) {
104
+ const wallet = new ethers_1.ethers.Wallet(key);
105
+ return {
106
+ address: wallet.address,
107
+ key,
108
+ type: 'privateKey',
109
+ };
110
+ }
111
+ decrypt(json, password) {
112
+ return __awaiter(this, void 0, void 0, function* () {
113
+ const wallet = yield ethers_1.ethers.Wallet.fromEncryptedJson(json, password);
114
+ return {
115
+ address: wallet.address,
116
+ key: wallet.privateKey,
117
+ type: 'privateKey',
118
+ };
119
+ });
120
+ }
121
+ transfer({ senderAccount, intent }) {
122
+ var _a;
123
+ return __awaiter(this, void 0, void 0, function* () {
124
+ const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
125
+ const wallet = new ethers_1.ethers.Wallet(senderAccount.key, provider);
126
+ let transaction;
127
+ const decimals = (_a = intent.tokenDecimals) !== null && _a !== void 0 ? _a : 18;
128
+ const amount = ethersBigNumber.parseFixed(intent.amount, decimals);
129
+ const isNative = constants_1.NATIVE_ASSETS.some(asset => asset.hash === intent.tokenHash);
130
+ if (!isNative) {
131
+ const contract = new ethers_1.ethers.Contract(intent.tokenHash, ['function transfer(address to, uint amount) returns (bool)'], wallet);
132
+ transaction = yield contract.transfer(intent.receiverAddress, amount);
133
+ }
134
+ else {
135
+ transaction = yield wallet.sendTransaction({
136
+ to: intent.receiverAddress,
137
+ value: amount,
138
+ });
139
+ }
140
+ const transactionMined = yield transaction.wait();
141
+ if (!transactionMined)
142
+ throw new Error('Transaction not mined');
143
+ return transactionMined.transactionHash;
144
+ });
145
+ }
146
+ calculateTransferFee({ senderAccount, intent }, details) {
147
+ var _a;
148
+ return __awaiter(this, void 0, void 0, function* () {
149
+ const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
150
+ const wallet = new ethers_1.ethers.Wallet(senderAccount.key, provider);
151
+ let estimated;
152
+ const isNative = constants_1.NATIVE_ASSETS.some(asset => asset.hash === intent.tokenHash);
153
+ const decimals = (_a = intent.tokenDecimals) !== null && _a !== void 0 ? _a : 18;
154
+ const amount = ethersBigNumber.parseFixed(intent.amount, decimals);
155
+ if (!isNative) {
156
+ const contract = new ethers_1.ethers.Contract(intent.tokenHash, ['function transfer(address to, uint amount) returns (bool)'], wallet);
157
+ estimated = yield contract.estimateGas.transfer(intent.receiverAddress, amount);
158
+ }
159
+ else {
160
+ estimated = yield wallet.estimateGas({
161
+ to: intent.receiverAddress,
162
+ value: amount,
163
+ });
164
+ }
165
+ return ethers_1.ethers.utils.formatEther(estimated);
166
+ });
167
+ }
168
+ resolveNameServiceDomain(domainName) {
169
+ return __awaiter(this, void 0, void 0, function* () {
170
+ const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
171
+ const address = yield provider.resolveName(domainName);
172
+ if (!address)
173
+ throw new Error('No address found for domain name');
174
+ return address;
175
+ });
176
+ }
177
+ }
178
+ exports.BSEthereum = BSEthereum;
@@ -0,0 +1,13 @@
1
+ import { BalanceResponse, ContractResponse, Token, TransactionsByAddressParams, TransactionsByAddressResponse, TransactionResponse, Network } from '@cityofzion/blockchain-service';
2
+ import { RpcBDSEthereum } from './RpcBDSEthereum';
3
+ export declare class BitqueryBDSEthereum extends RpcBDSEthereum {
4
+ private readonly client;
5
+ private readonly networkType;
6
+ constructor(network: Network);
7
+ getTransaction(hash: string): Promise<TransactionResponse>;
8
+ getTransactionsByAddress({ address, page, }: TransactionsByAddressParams): Promise<TransactionsByAddressResponse>;
9
+ getContract(): Promise<ContractResponse>;
10
+ getTokenInfo(hash: string): Promise<Token>;
11
+ getBalance(address: string): Promise<BalanceResponse[]>;
12
+ private parseTransactionTransfer;
13
+ }
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.BitqueryBDSEthereum = void 0;
16
+ const core_1 = require("@urql/core");
17
+ const node_fetch_1 = __importDefault(require("node-fetch"));
18
+ const constants_1 = require("./constants");
19
+ const graphql_1 = require("./graphql");
20
+ const RpcBDSEthereum_1 = require("./RpcBDSEthereum");
21
+ class BitqueryBDSEthereum extends RpcBDSEthereum_1.RpcBDSEthereum {
22
+ constructor(network) {
23
+ super(network);
24
+ if (network.type === 'custom')
25
+ throw new Error('Custom network not supported');
26
+ this.networkType = network.type;
27
+ this.client = new core_1.Client({
28
+ url: constants_1.BITQUERY_URL,
29
+ exchanges: [core_1.fetchExchange],
30
+ fetch: node_fetch_1.default,
31
+ fetchOptions: {
32
+ headers: {
33
+ 'X-API-KEY': constants_1.BITQUERY_API_KEY,
34
+ },
35
+ },
36
+ });
37
+ }
38
+ getTransaction(hash) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ const result = yield this.client
41
+ .query(graphql_1.bitqueryGetTransactionQuery, {
42
+ hash,
43
+ network: constants_1.BITQUERY_NETWORK_BY_NETWORK_TYPE[this.networkType],
44
+ })
45
+ .toPromise();
46
+ if (result.error)
47
+ throw new Error(result.error.message);
48
+ if (!result.data || !result.data.ethereum.transfers.length)
49
+ throw new Error('Transaction not found');
50
+ const transfers = result.data.ethereum.transfers.map(this.parseTransactionTransfer);
51
+ const { block: { height, timestamp: { unixtime }, }, transaction: { gasValue, hash: transactionHash }, } = result.data.ethereum.transfers[0];
52
+ return {
53
+ block: height,
54
+ time: unixtime,
55
+ hash: transactionHash,
56
+ fee: String(gasValue),
57
+ transfers,
58
+ notifications: [],
59
+ };
60
+ });
61
+ }
62
+ getTransactionsByAddress({ address, page = 1, }) {
63
+ var _a, _b, _c, _d, _e, _f, _g, _h;
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ const limit = 10;
66
+ const offset = limit * (page - 1);
67
+ const result = yield this.client
68
+ .query(graphql_1.bitqueryGetTransactionsByAddressQuery, {
69
+ address,
70
+ limit,
71
+ offset,
72
+ network: constants_1.BITQUERY_NETWORK_BY_NETWORK_TYPE[this.networkType],
73
+ })
74
+ .toPromise();
75
+ if (result.error)
76
+ throw new Error(result.error.message);
77
+ if (!result.data)
78
+ throw new Error('Address does not have transactions');
79
+ const totalCount = ((_a = result.data.ethereum.sentCount[0].count) !== null && _a !== void 0 ? _a : 0) + ((_b = result.data.ethereum.receiverCount[0].count) !== null && _b !== void 0 ? _b : 0);
80
+ const mixedTransfers = [...((_e = (_d = (_c = result === null || result === void 0 ? void 0 : result.data) === null || _c === void 0 ? void 0 : _c.ethereum) === null || _d === void 0 ? void 0 : _d.sent) !== null && _e !== void 0 ? _e : []), ...((_h = (_g = (_f = result === null || result === void 0 ? void 0 : result.data) === null || _f === void 0 ? void 0 : _f.ethereum) === null || _g === void 0 ? void 0 : _g.received) !== null && _h !== void 0 ? _h : [])];
81
+ const transactions = new Map();
82
+ mixedTransfers.forEach(transfer => {
83
+ const transactionTransfer = this.parseTransactionTransfer(transfer);
84
+ const existingTransaction = transactions.get(transfer.transaction.hash);
85
+ if (existingTransaction) {
86
+ existingTransaction.transfers.push(transactionTransfer);
87
+ return;
88
+ }
89
+ transactions.set(transfer.transaction.hash, {
90
+ block: transfer.block.height,
91
+ hash: transfer.transaction.hash,
92
+ time: transfer.block.timestamp.unixtime,
93
+ fee: String(transfer.transaction.gasValue),
94
+ transfers: [transactionTransfer],
95
+ notifications: [],
96
+ });
97
+ });
98
+ return {
99
+ totalCount,
100
+ limit: limit * 2,
101
+ transactions: Array.from(transactions.values()),
102
+ };
103
+ });
104
+ }
105
+ getContract() {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ throw new Error("Bitquery doesn't support contract info");
108
+ });
109
+ }
110
+ getTokenInfo(hash) {
111
+ return __awaiter(this, void 0, void 0, function* () {
112
+ const localToken = constants_1.TOKENS[this.networkType].find(token => token.hash === hash);
113
+ if (localToken)
114
+ return localToken;
115
+ const result = yield this.client
116
+ .query(graphql_1.bitqueryGetTokenInfoQuery, {
117
+ hash,
118
+ network: constants_1.BITQUERY_NETWORK_BY_NETWORK_TYPE[this.networkType],
119
+ })
120
+ .toPromise();
121
+ if (result.error)
122
+ throw new Error(result.error.message);
123
+ if (!result.data || result.data.ethereum.smartContractCalls.length <= 0)
124
+ throw new Error('Token not found');
125
+ const { address: { address }, currency: { decimals, name, symbol, tokenType }, } = result.data.ethereum.smartContractCalls[0].smartContract;
126
+ if (tokenType !== 'ERC20')
127
+ throw new Error('Token is not ERC20');
128
+ return {
129
+ hash: address,
130
+ name,
131
+ symbol,
132
+ decimals,
133
+ };
134
+ });
135
+ }
136
+ getBalance(address) {
137
+ var _a, _b;
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const result = yield this.client
140
+ .query(graphql_1.bitqueryGetBalanceQuery, {
141
+ address,
142
+ network: constants_1.BITQUERY_NETWORK_BY_NETWORK_TYPE[this.networkType],
143
+ })
144
+ .toPromise();
145
+ if (result.error)
146
+ throw new Error(result.error.message);
147
+ const data = (_b = (_a = result.data) === null || _a === void 0 ? void 0 : _a.ethereum.address[0].balances) !== null && _b !== void 0 ? _b : [];
148
+ const balances = data.map(({ value, currency: { address, decimals, name, symbol } }) => ({
149
+ amount: value.toString(),
150
+ token: {
151
+ hash: address,
152
+ symbol,
153
+ name,
154
+ decimals,
155
+ },
156
+ }));
157
+ return balances;
158
+ });
159
+ }
160
+ parseTransactionTransfer({ amount, currency: { tokenType, address, decimals, name, symbol }, entityId, sender, receiver, }) {
161
+ if (tokenType === 'ERC721') {
162
+ return {
163
+ from: sender.address,
164
+ to: receiver.address,
165
+ tokenId: entityId,
166
+ contractHash: address,
167
+ type: 'nft',
168
+ };
169
+ }
170
+ return {
171
+ from: sender.address,
172
+ to: receiver.address,
173
+ contractHash: address,
174
+ amount: amount.toString(),
175
+ token: {
176
+ decimals: decimals,
177
+ hash: address,
178
+ name: name,
179
+ symbol: symbol,
180
+ },
181
+ type: 'token',
182
+ };
183
+ }
184
+ }
185
+ exports.BitqueryBDSEthereum = BitqueryBDSEthereum;
@@ -0,0 +1,8 @@
1
+ import { Currency, ExchangeDataService, NetworkType, TokenPricesResponse } from '@cityofzion/blockchain-service';
2
+ export declare class BitqueryEDSEthereum implements ExchangeDataService {
3
+ private readonly client;
4
+ private readonly networkType;
5
+ constructor(networkType: NetworkType);
6
+ getTokenPrices(currency: Currency): Promise<TokenPricesResponse[]>;
7
+ private getCurrencyRatio;
8
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.BitqueryEDSEthereum = void 0;
16
+ const core_1 = require("@urql/core");
17
+ const node_fetch_1 = __importDefault(require("node-fetch"));
18
+ const constants_1 = require("./constants");
19
+ const dayjs_1 = __importDefault(require("dayjs"));
20
+ const utc_1 = __importDefault(require("dayjs/plugin/utc"));
21
+ const graphql_1 = require("./graphql");
22
+ dayjs_1.default.extend(utc_1.default);
23
+ class BitqueryEDSEthereum {
24
+ constructor(networkType) {
25
+ this.networkType = networkType;
26
+ this.client = new core_1.Client({
27
+ url: constants_1.BITQUERY_URL,
28
+ exchanges: [core_1.fetchExchange],
29
+ fetch: node_fetch_1.default,
30
+ fetchOptions: {
31
+ headers: {
32
+ 'X-API-KEY': constants_1.BITQUERY_API_KEY,
33
+ },
34
+ },
35
+ });
36
+ }
37
+ getTokenPrices(currency) {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ if (this.networkType !== 'mainnet')
40
+ throw new Error('Exchange is only available on mainnet');
41
+ const twoDaysAgo = dayjs_1.default.utc().subtract(2, 'day').startOf('date').toISOString();
42
+ const result = yield this.client
43
+ .query(graphql_1.bitqueryGetPricesQuery, { after: twoDaysAgo, network: 'ethereum' })
44
+ .toPromise();
45
+ if (result.error) {
46
+ throw new Error(result.error.message);
47
+ }
48
+ if (!result.data) {
49
+ throw new Error('There is no price data');
50
+ }
51
+ let currencyRatio = 1;
52
+ if (currency !== 'USD') {
53
+ currencyRatio = yield this.getCurrencyRatio(currency);
54
+ }
55
+ const prices = result.data.ethereum.dexTrades.map((trade) => ({
56
+ symbol: trade.baseCurrency.symbol,
57
+ price: trade.quotePrice * currencyRatio,
58
+ }));
59
+ return prices;
60
+ });
61
+ }
62
+ getCurrencyRatio(currency) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ const request = yield (0, node_fetch_1.default)(`https://api.flamingo.finance/fiat/exchange-rate?pair=USD_${currency}`, {
65
+ method: 'GET',
66
+ });
67
+ const data = yield request.json();
68
+ return data;
69
+ });
70
+ }
71
+ }
72
+ exports.BitqueryEDSEthereum = BitqueryEDSEthereum;
@@ -0,0 +1,10 @@
1
+ import { NftResponse, NftsResponse, NetworkType, NftDataService, GetNftParam, GetNftsByAddressParams } from '@cityofzion/blockchain-service';
2
+ export declare class GhostMarketNDSEthereum implements NftDataService {
3
+ private networkType;
4
+ constructor(networkType: NetworkType);
5
+ getNftsByAddress({ address, size, cursor, page }: GetNftsByAddressParams): Promise<NftsResponse>;
6
+ getNft({ contractHash, tokenId }: GetNftParam): Promise<NftResponse>;
7
+ private treatGhostMarketImage;
8
+ private getUrlWithParams;
9
+ private parse;
10
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.GhostMarketNDSEthereum = void 0;
16
+ const query_string_1 = __importDefault(require("query-string"));
17
+ const constants_1 = require("./constants");
18
+ const node_fetch_1 = __importDefault(require("node-fetch"));
19
+ class GhostMarketNDSEthereum {
20
+ constructor(networkType) {
21
+ this.networkType = networkType;
22
+ }
23
+ getNftsByAddress({ address, size = 18, cursor, page }) {
24
+ var _a;
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ const url = this.getUrlWithParams({
27
+ size,
28
+ owners: [address],
29
+ cursor: cursor,
30
+ });
31
+ const request = yield (0, node_fetch_1.default)(url, { method: 'GET' });
32
+ const data = (yield request.json());
33
+ const nfts = (_a = data.assets) !== null && _a !== void 0 ? _a : [];
34
+ return { nextCursor: data.next, items: nfts.map(this.parse.bind(this)) };
35
+ });
36
+ }
37
+ getNft({ contractHash, tokenId }) {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ const url = this.getUrlWithParams({
40
+ contract: contractHash,
41
+ tokenIds: [tokenId],
42
+ });
43
+ const request = yield (0, node_fetch_1.default)(url, { method: 'GET' });
44
+ const data = (yield request.json());
45
+ return this.parse(data.assets[0]);
46
+ });
47
+ }
48
+ treatGhostMarketImage(srcImage) {
49
+ if (!srcImage) {
50
+ return;
51
+ }
52
+ if (srcImage.startsWith('ipfs://')) {
53
+ const [, imageId] = srcImage.split('://');
54
+ return `https://ghostmarket.mypinata.cloud/ipfs/${imageId}`;
55
+ }
56
+ return srcImage;
57
+ }
58
+ getUrlWithParams(params) {
59
+ const parameters = query_string_1.default.stringify(Object.assign({ chain: constants_1.GHOSTMARKET_CHAIN_BY_NETWORK_TYPE[this.networkType] }, params), { arrayFormat: 'bracket' });
60
+ return `${constants_1.GHOSTMARKET_URL_BY_NETWORK_TYPE[this.networkType]}/assets?${parameters}`;
61
+ }
62
+ parse(data) {
63
+ var _a, _b;
64
+ const nftResponse = {
65
+ collectionImage: this.treatGhostMarketImage((_a = data.collection) === null || _a === void 0 ? void 0 : _a.logoUrl),
66
+ id: data.tokenId,
67
+ contractHash: data.contract.hash,
68
+ symbol: data.contract.symbol,
69
+ collectionName: (_b = data.collection) === null || _b === void 0 ? void 0 : _b.name,
70
+ image: this.treatGhostMarketImage(data.metadata.mediaUri),
71
+ isSVG: String(data.metadata.mediaType).includes('svg+xml'),
72
+ name: data.metadata.name,
73
+ };
74
+ return nftResponse;
75
+ }
76
+ }
77
+ exports.GhostMarketNDSEthereum = GhostMarketNDSEthereum;
@@ -0,0 +1,11 @@
1
+ import { BalanceResponse, BlockchainDataService, ContractResponse, Network, Token, TransactionResponse, TransactionsByAddressParams, TransactionsByAddressResponse } from '@cityofzion/blockchain-service';
2
+ export declare class RpcBDSEthereum implements BlockchainDataService {
3
+ private readonly network;
4
+ constructor(network: Network);
5
+ getTransaction(hash: string): Promise<TransactionResponse>;
6
+ getTransactionsByAddress(_params: TransactionsByAddressParams): Promise<TransactionsByAddressResponse>;
7
+ getContract(): Promise<ContractResponse>;
8
+ getTokenInfo(hash: string): Promise<Token>;
9
+ getBalance(address: string): Promise<BalanceResponse[]>;
10
+ getBlockHeight(): Promise<number>;
11
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RpcBDSEthereum = void 0;
13
+ const ethers_1 = require("ethers");
14
+ const constants_1 = require("./constants");
15
+ class RpcBDSEthereum {
16
+ constructor(network) {
17
+ this.network = network;
18
+ }
19
+ getTransaction(hash) {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
22
+ const transaction = yield provider.getTransaction(hash);
23
+ if (!transaction || !transaction.blockHash || !transaction.to)
24
+ throw new Error('Transaction not found');
25
+ const block = yield provider.getBlock(transaction.blockHash);
26
+ if (!block)
27
+ throw new Error('Block not found');
28
+ const tokens = constants_1.TOKENS[this.network.type];
29
+ const token = tokens.find(token => token.symbol === 'ETH');
30
+ return {
31
+ block: block.number,
32
+ time: block.timestamp,
33
+ hash: transaction.hash,
34
+ transfers: [
35
+ {
36
+ type: 'token',
37
+ amount: ethers_1.ethers.utils.formatEther(transaction.value),
38
+ contractHash: '-',
39
+ from: transaction.from,
40
+ to: transaction.to,
41
+ token,
42
+ },
43
+ ],
44
+ notifications: [],
45
+ };
46
+ });
47
+ }
48
+ getTransactionsByAddress(_params) {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ throw new Error("RPC doesn't support get transactions history of address");
51
+ });
52
+ }
53
+ getContract() {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ throw new Error("RPC doesn't support contract info");
56
+ });
57
+ }
58
+ getTokenInfo(hash) {
59
+ return __awaiter(this, void 0, void 0, function* () {
60
+ const tokens = constants_1.TOKENS[this.network.type];
61
+ const token = tokens.find(token => token.hash === hash);
62
+ if (!token)
63
+ throw new Error('Token not found');
64
+ return token;
65
+ });
66
+ }
67
+ getBalance(address) {
68
+ return __awaiter(this, void 0, void 0, function* () {
69
+ const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
70
+ const balance = yield provider.getBalance(address);
71
+ const tokens = constants_1.TOKENS[this.network.type];
72
+ const token = tokens.find(token => token.symbol === 'ETH');
73
+ return [
74
+ {
75
+ amount: ethers_1.ethers.utils.formatEther(balance),
76
+ token,
77
+ },
78
+ ];
79
+ });
80
+ }
81
+ getBlockHeight() {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ const provider = new ethers_1.ethers.providers.JsonRpcProvider(this.network.url);
84
+ return yield provider.getBlockNumber();
85
+ });
86
+ }
87
+ }
88
+ exports.RpcBDSEthereum = RpcBDSEthereum;
@@ -0,0 +1,8 @@
1
+ [
2
+ {
3
+ "symbol": "ETH",
4
+ "name": "Ethereum",
5
+ "hash": "-",
6
+ "decimals": 16
7
+ }
8
+ ]
@@ -0,0 +1,16 @@
1
+ import { NetworkType, Token } from '@cityofzion/blockchain-service';
2
+ export type BitqueryNetwork = 'ethereum' | 'goerli';
3
+ export declare const TOKENS: Record<NetworkType, Token[]>;
4
+ export declare const NATIVE_ASSETS: {
5
+ symbol: string;
6
+ name: string;
7
+ hash: string;
8
+ decimals: number;
9
+ }[];
10
+ export declare const DEFAULT_URL_BY_NETWORK_TYPE: Record<NetworkType, string>;
11
+ export declare const BITQUERY_API_KEY = "BQYMp76Ny15C8ORbI2BOstFUhoMCahLI";
12
+ export declare const BITQUERY_URL = "https://graphql.bitquery.io";
13
+ export declare const BITQUERY_NETWORK_BY_NETWORK_TYPE: Record<Exclude<NetworkType, 'custom'>, BitqueryNetwork>;
14
+ export declare const GHOSTMARKET_URL_BY_NETWORK_TYPE: Partial<Record<NetworkType, string>>;
15
+ export declare const GHOSTMARKET_CHAIN_BY_NETWORK_TYPE: Partial<Record<NetworkType, string>>;
16
+ export declare const DERIVATION_PATH = "m/44'/60'/0'/0/?";
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DERIVATION_PATH = exports.GHOSTMARKET_CHAIN_BY_NETWORK_TYPE = exports.GHOSTMARKET_URL_BY_NETWORK_TYPE = exports.BITQUERY_NETWORK_BY_NETWORK_TYPE = exports.BITQUERY_URL = exports.BITQUERY_API_KEY = exports.DEFAULT_URL_BY_NETWORK_TYPE = exports.NATIVE_ASSETS = exports.TOKENS = void 0;
7
+ const common_json_1 = __importDefault(require("./assets/tokens/common.json"));
8
+ exports.TOKENS = {
9
+ mainnet: [...common_json_1.default],
10
+ testnet: common_json_1.default,
11
+ custom: common_json_1.default,
12
+ };
13
+ exports.NATIVE_ASSETS = common_json_1.default;
14
+ exports.DEFAULT_URL_BY_NETWORK_TYPE = {
15
+ mainnet: 'https://ethereum-mainnet-rpc.allthatnode.com',
16
+ testnet: 'https://ethereum-goerli-rpc.allthatnode.com',
17
+ custom: 'http://127.0.0.1:8545',
18
+ };
19
+ exports.BITQUERY_API_KEY = 'BQYMp76Ny15C8ORbI2BOstFUhoMCahLI';
20
+ exports.BITQUERY_URL = 'https://graphql.bitquery.io';
21
+ exports.BITQUERY_NETWORK_BY_NETWORK_TYPE = {
22
+ mainnet: 'ethereum',
23
+ testnet: 'goerli',
24
+ };
25
+ exports.GHOSTMARKET_URL_BY_NETWORK_TYPE = {
26
+ mainnet: 'https://api.ghostmarket.io/api/v2',
27
+ testnet: 'https://api-testnet.ghostmarket.io/api/v2',
28
+ };
29
+ exports.GHOSTMARKET_CHAIN_BY_NETWORK_TYPE = {
30
+ mainnet: 'eth',
31
+ testnet: 'etht',
32
+ };
33
+ exports.DERIVATION_PATH = "m/44'/60'/0'/0/?";
@@ -0,0 +1,123 @@
1
+ type BitqueryNetwork = 'ethereum' | 'goerli';
2
+ export type BitqueryTransaction = {
3
+ block: {
4
+ timestamp: {
5
+ unixtime: number;
6
+ };
7
+ height: number;
8
+ };
9
+ transaction: {
10
+ gasValue: number;
11
+ hash: string;
12
+ };
13
+ amount: number;
14
+ currency: {
15
+ address: string;
16
+ tokenType: string;
17
+ decimals: number;
18
+ symbol: string;
19
+ name: string;
20
+ };
21
+ sender: {
22
+ address: string;
23
+ };
24
+ receiver: {
25
+ address: string;
26
+ };
27
+ entityId: string;
28
+ };
29
+ type BitQueryGetTransactionsByAddressResponse = {
30
+ ethereum: {
31
+ sent: BitqueryTransaction[];
32
+ received: BitqueryTransaction[];
33
+ sentCount: {
34
+ count: number;
35
+ }[];
36
+ receiverCount: {
37
+ count: number;
38
+ }[];
39
+ };
40
+ };
41
+ type BitQueryGetTransactionsByAddressVariables = {
42
+ address: string;
43
+ limit: number;
44
+ offset: number;
45
+ network: BitqueryNetwork;
46
+ };
47
+ export declare const bitqueryGetTransactionsByAddressQuery: import("@urql/core/dist/urql-core-chunk").TypedDocumentNode<BitQueryGetTransactionsByAddressResponse, BitQueryGetTransactionsByAddressVariables>;
48
+ type BitQueryGetTransactionResponse = {
49
+ ethereum: {
50
+ transfers: BitqueryTransaction[];
51
+ };
52
+ };
53
+ type BitQueryGetTransactionVariables = {
54
+ hash: string;
55
+ network: BitqueryNetwork;
56
+ };
57
+ export declare const bitqueryGetTransactionQuery: import("@urql/core/dist/urql-core-chunk").TypedDocumentNode<BitQueryGetTransactionResponse, BitQueryGetTransactionVariables>;
58
+ type BitQueryGetContractResponse = {
59
+ ethereum: {
60
+ smartContractCalls: {
61
+ smartContract: {
62
+ address: {
63
+ address: string;
64
+ };
65
+ currency: {
66
+ symbol: string;
67
+ name: string;
68
+ decimals: number;
69
+ tokenType: string;
70
+ };
71
+ };
72
+ }[];
73
+ };
74
+ };
75
+ type BitQueryGetTokenInfoVariables = {
76
+ hash: string;
77
+ network: BitqueryNetwork;
78
+ };
79
+ export declare const bitqueryGetTokenInfoQuery: import("@urql/core/dist/urql-core-chunk").TypedDocumentNode<BitQueryGetContractResponse, BitQueryGetTokenInfoVariables>;
80
+ type BitQueryGetBalanceResponse = {
81
+ ethereum: {
82
+ address: {
83
+ balances: {
84
+ currency: {
85
+ address: string;
86
+ symbol: string;
87
+ name: string;
88
+ decimals: number;
89
+ };
90
+ value: number;
91
+ }[] | null;
92
+ }[];
93
+ };
94
+ };
95
+ type BitQueryGetBalanceVariables = {
96
+ address: string;
97
+ network: BitqueryNetwork;
98
+ };
99
+ export declare const bitqueryGetBalanceQuery: import("@urql/core/dist/urql-core-chunk").TypedDocumentNode<BitQueryGetBalanceResponse, BitQueryGetBalanceVariables>;
100
+ type BitQueryGetTokenPricesResponse = {
101
+ ethereum: {
102
+ dexTrades: {
103
+ baseCurrency: {
104
+ address: string;
105
+ symbol: string;
106
+ };
107
+ quoteCurrency: {
108
+ address: string;
109
+ symbol: string;
110
+ };
111
+ date: {
112
+ date: string;
113
+ };
114
+ quotePrice: number;
115
+ }[];
116
+ };
117
+ };
118
+ export type BitQueryGetTokenPricesVariables = {
119
+ after: string;
120
+ network: BitqueryNetwork;
121
+ };
122
+ export declare const bitqueryGetPricesQuery: import("@urql/core/dist/urql-core-chunk").TypedDocumentNode<BitQueryGetTokenPricesResponse, BitQueryGetTokenPricesVariables>;
123
+ export {};
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bitqueryGetPricesQuery = exports.bitqueryGetBalanceQuery = exports.bitqueryGetTokenInfoQuery = exports.bitqueryGetTransactionQuery = exports.bitqueryGetTransactionsByAddressQuery = void 0;
4
+ const core_1 = require("@urql/core");
5
+ exports.bitqueryGetTransactionsByAddressQuery = (0, core_1.gql) `
6
+ query getTransactions($address: String!, $limit: Int!, $offset: Int!, $network: EthereumNetwork!) {
7
+ ethereum(network: $network) {
8
+ sent: transfers(
9
+ options: { limit: $limit, offset: $offset, desc: "block.timestamp.unixtime" }
10
+ sender: { is: $address }
11
+ ) {
12
+ block {
13
+ timestamp {
14
+ unixtime
15
+ }
16
+ height
17
+ }
18
+ amount
19
+ currency {
20
+ address
21
+ tokenType
22
+ symbol
23
+ decimals
24
+ name
25
+ }
26
+ sender {
27
+ address
28
+ }
29
+ receiver {
30
+ address
31
+ }
32
+ transaction {
33
+ gasValue
34
+ hash
35
+ }
36
+ entityId
37
+ }
38
+ received: transfers(
39
+ options: { limit: $limit, offset: $offset, desc: "block.timestamp.unixtime" }
40
+ receiver: { is: $address }
41
+ ) {
42
+ block {
43
+ timestamp {
44
+ unixtime
45
+ }
46
+ height
47
+ }
48
+ amount
49
+ currency {
50
+ address
51
+ tokenType
52
+ }
53
+ sender {
54
+ address
55
+ }
56
+ receiver {
57
+ address
58
+ }
59
+ transaction {
60
+ gasValue
61
+ hash
62
+ }
63
+ entityId
64
+ }
65
+ sentCount: transfers(sender: { is: $address }) {
66
+ count
67
+ }
68
+ receiverCount: transfers(receiver: { is: $address }) {
69
+ count
70
+ }
71
+ }
72
+ }
73
+ `;
74
+ exports.bitqueryGetTransactionQuery = (0, core_1.gql) `
75
+ query getTransaction($hash: String!, $network: EthereumNetwork!) {
76
+ ethereum(network: $network) {
77
+ transfers(txHash: { is: $hash }) {
78
+ block {
79
+ timestamp {
80
+ unixtime
81
+ }
82
+ height
83
+ }
84
+ amount
85
+ currency {
86
+ address
87
+ tokenType
88
+ }
89
+ sender {
90
+ address
91
+ }
92
+ receiver {
93
+ address
94
+ }
95
+ transaction {
96
+ gasValue
97
+ hash
98
+ }
99
+ entityId
100
+ }
101
+ }
102
+ }
103
+ `;
104
+ exports.bitqueryGetTokenInfoQuery = (0, core_1.gql) `
105
+ query getTokenInfo($hash: String!, $network: EthereumNetwork!) {
106
+ ethereum(network: $network) {
107
+ smartContractCalls(smartContractAddress: { is: $hash }) {
108
+ smartContract {
109
+ address {
110
+ address
111
+ }
112
+ currency {
113
+ symbol
114
+ name
115
+ decimals
116
+ tokenType
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+ `;
123
+ exports.bitqueryGetBalanceQuery = (0, core_1.gql) `
124
+ query getBalance($address: String!, $network: EthereumNetwork!) {
125
+ ethereum(network: $network) {
126
+ address(address: { is: $address }) {
127
+ balances {
128
+ currency {
129
+ address
130
+ symbol
131
+ name
132
+ decimals
133
+ }
134
+ value
135
+ }
136
+ }
137
+ }
138
+ }
139
+ `;
140
+ exports.bitqueryGetPricesQuery = (0, core_1.gql) `
141
+ query getPrice($after: ISO8601DateTime!, $network: EthereumNetwork!) {
142
+ ethereum(network: $network) {
143
+ dexTrades(
144
+ options: { limitBy: { each: "baseCurrency.address", limit: 1 }, desc: "date.date" }
145
+ time: { after: $after }
146
+ ) {
147
+ quoteCurrency(quoteCurrency: { is: "0xdac17f958d2ee523a2206206994597c13d831ec7" }) {
148
+ symbol
149
+ address
150
+ }
151
+ baseCurrency {
152
+ symbol
153
+ address
154
+ }
155
+ date {
156
+ date
157
+ }
158
+ quotePrice
159
+ }
160
+ }
161
+ }
162
+ `;
@@ -0,0 +1,6 @@
1
+ export * from './BSEthereum';
2
+ export * from './GhostMarketNDSEthereum';
3
+ export * from './constants';
4
+ export * from './BitqueryBDSEthereum';
5
+ export * from './BitqueryEDSEthereum';
6
+ export * from './RpcBDSEthereum';
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./BSEthereum"), exports);
18
+ __exportStar(require("./GhostMarketNDSEthereum"), exports);
19
+ __exportStar(require("./constants"), exports);
20
+ __exportStar(require("./BitqueryBDSEthereum"), exports);
21
+ __exportStar(require("./BitqueryEDSEthereum"), exports);
22
+ __exportStar(require("./RpcBDSEthereum"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cityofzion/bs-ethereum",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": "https://github.com/CityOfZion/blockchain-services",
@@ -11,7 +11,7 @@
11
11
  "test": "jest --config jest.config.ts"
12
12
  },
13
13
  "dependencies": {
14
- "@cityofzion/blockchain-service": "0.7.0",
14
+ "@cityofzion/blockchain-service": "0.7.2",
15
15
  "ethers": "5.7.2",
16
16
  "@urql/core": "~4.1.1",
17
17
  "graphql": "~16.8.0",
@@ -10,7 +10,7 @@ import {
10
10
  TransactionTransferNft,
11
11
  Network,
12
12
  } from '@cityofzion/blockchain-service'
13
- import { Client, cacheExchange, fetchExchange, gql } from '@urql/core'
13
+ import { Client, fetchExchange } from '@urql/core'
14
14
  import fetch from 'node-fetch'
15
15
  import { BITQUERY_API_KEY, BITQUERY_NETWORK_BY_NETWORK_TYPE, BITQUERY_URL, TOKENS } from './constants'
16
16
  import {
@@ -34,7 +34,7 @@ export class BitqueryBDSEthereum extends RpcBDSEthereum {
34
34
 
35
35
  this.client = new Client({
36
36
  url: BITQUERY_URL,
37
- exchanges: [cacheExchange, fetchExchange],
37
+ exchanges: [fetchExchange],
38
38
  fetch,
39
39
  fetchOptions: {
40
40
  headers: {
@@ -93,7 +93,8 @@ export class BitqueryBDSEthereum extends RpcBDSEthereum {
93
93
  if (result.error) throw new Error(result.error.message)
94
94
  if (!result.data) throw new Error('Address does not have transactions')
95
95
 
96
- const totalCount = (result.data.ethereum.sentCount.count ?? 0) + (result.data.ethereum.receiverCount.count ?? 0)
96
+ const totalCount =
97
+ (result.data.ethereum.sentCount[0].count ?? 0) + (result.data.ethereum.receiverCount[0].count ?? 0)
97
98
  const mixedTransfers = [...(result?.data?.ethereum?.sent ?? []), ...(result?.data?.ethereum?.received ?? [])]
98
99
 
99
100
  const transactions = new Map<string, TransactionResponse>()
@@ -1,5 +1,5 @@
1
1
  import { Currency, ExchangeDataService, NetworkType, TokenPricesResponse } from '@cityofzion/blockchain-service'
2
- import { Client, cacheExchange, fetchExchange, gql } from '@urql/core'
2
+ import { Client, fetchExchange } from '@urql/core'
3
3
  import fetch from 'node-fetch'
4
4
  import { BITQUERY_API_KEY, BITQUERY_URL } from './constants'
5
5
  import dayjs from 'dayjs'
@@ -16,7 +16,7 @@ export class BitqueryEDSEthereum implements ExchangeDataService {
16
16
 
17
17
  this.client = new Client({
18
18
  url: BITQUERY_URL,
19
- exchanges: [cacheExchange, fetchExchange],
19
+ exchanges: [fetchExchange],
20
20
  fetch,
21
21
  fetchOptions: {
22
22
  headers: {
@@ -41,6 +41,7 @@ describe('BDSEthereum', () => {
41
41
  async (BDSEthereum: BlockchainDataService) => {
42
42
  const address = '0x82B5Cd984880C8A821429cFFf89f36D35BaeBE89'
43
43
  const response = await BDSEthereum.getTransactionsByAddress({ address: address, page: 1 })
44
+ expect(response.totalCount).toBeGreaterThan(0)
44
45
  response.transactions.forEach(transaction => {
45
46
  expect(transaction).toEqual(
46
47
  expect.objectContaining({
package/src/graphql.ts CHANGED
@@ -36,10 +36,10 @@ type BitQueryGetTransactionsByAddressResponse = {
36
36
  received: BitqueryTransaction[]
37
37
  sentCount: {
38
38
  count: number
39
- }
39
+ }[]
40
40
  receiverCount: {
41
41
  count: number
42
- }
42
+ }[]
43
43
  }
44
44
  }
45
45
 
@@ -56,7 +56,10 @@ export const bitqueryGetTransactionsByAddressQuery = gql<
56
56
  >`
57
57
  query getTransactions($address: String!, $limit: Int!, $offset: Int!, $network: EthereumNetwork!) {
58
58
  ethereum(network: $network) {
59
- sent: transfers(options: { limit: $limit, offset: $offset }, sender: { is: $address }) {
59
+ sent: transfers(
60
+ options: { limit: $limit, offset: $offset, desc: "block.timestamp.unixtime" }
61
+ sender: { is: $address }
62
+ ) {
60
63
  block {
61
64
  timestamp {
62
65
  unixtime
@@ -83,7 +86,10 @@ export const bitqueryGetTransactionsByAddressQuery = gql<
83
86
  }
84
87
  entityId
85
88
  }
86
- received: transfers(options: { limit: $limit, offset: $offset }, receiver: { is: $address }) {
89
+ received: transfers(
90
+ options: { limit: $limit, offset: $offset, desc: "block.timestamp.unixtime" }
91
+ receiver: { is: $address }
92
+ ) {
87
93
  block {
88
94
  timestamp {
89
95
  unixtime