@cityofzion/bs-solana 0.0.1 → 2.0.0
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.
- package/dist/BSSolana.d.ts +36 -0
- package/dist/BSSolana.js +271 -0
- package/dist/constants/BSSolanaConstants.d.ts +15 -0
- package/dist/constants/BSSolanaConstants.js +34 -0
- package/dist/helpers/BSSolanaCachedMethodsHelper.d.ts +13 -0
- package/dist/helpers/BSSolanaCachedMethodsHelper.js +148 -0
- package/dist/helpers/BSSolanaHelper.d.ts +7 -0
- package/dist/helpers/BSSolanaHelper.js +16 -0
- package/dist/services/blockchain-data/TatumRpcBDSSolana.d.ts +19 -0
- package/dist/services/blockchain-data/TatumRpcBDSSolana.js +408 -0
- package/dist/services/exchange/MoralisEDSSolana.d.ts +8 -0
- package/dist/services/exchange/MoralisEDSSolana.js +104 -0
- package/dist/services/explorer/SolScanESSolana.d.ts +13 -0
- package/dist/services/explorer/SolScanESSolana.js +50 -0
- package/dist/services/ledger/Web3LedgerServiceSolana.d.ts +13 -0
- package/dist/services/ledger/Web3LedgerServiceSolana.js +85 -0
- package/dist/services/nft-data/TatumRpcNDSSolana.d.ts +9 -0
- package/dist/services/nft-data/TatumRpcNDSSolana.js +129 -0
- package/dist/services/token/TokenServiceSolana.d.ts +4 -0
- package/dist/services/token/TokenServiceSolana.js +10 -0
- package/package.json +40 -11
|
@@ -0,0 +1,408 @@
|
|
|
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 () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
45
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
46
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
47
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
48
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
49
|
+
};
|
|
50
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
51
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
52
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
53
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
54
|
+
};
|
|
55
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
56
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
57
|
+
};
|
|
58
|
+
var _TatumRpcBDSSolana_instances, _TatumRpcBDSSolana_network, _TatumRpcBDSSolana_feeToken, _TatumRpcBDSSolana_connection, _TatumRpcBDSSolana_mainnetApiKey, _TatumRpcBDSSolana_testnetApiKey, _TatumRpcBDSSolana_functionByProgramIdAndMethod, _TatumRpcBDSSolana_parseSplTransferCheckedInstruction, _TatumRpcBDSSolana_parseSplTransferInstruction, _TatumRpcBDSSolana_parseSystemInstruction, _TatumRpcBDSSolana_parseInstruction;
|
|
59
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
+
exports.TatumRpcBDSSolana = void 0;
|
|
61
|
+
const blockchain_service_1 = require("@cityofzion/blockchain-service");
|
|
62
|
+
const BSSolanaConstants_1 = require("../../constants/BSSolanaConstants");
|
|
63
|
+
const web3_js_1 = __importDefault(require("@solana/web3.js"));
|
|
64
|
+
const solanaSplSDK = __importStar(require("@solana/spl-token"));
|
|
65
|
+
const BSSolanaCachedMethodsHelper_1 = require("../../helpers/BSSolanaCachedMethodsHelper");
|
|
66
|
+
const BSSolanaHelper_1 = require("../../helpers/BSSolanaHelper");
|
|
67
|
+
class TatumRpcBDSSolana {
|
|
68
|
+
static getTatumConnection(network, apiKey) {
|
|
69
|
+
return new web3_js_1.default.Connection(this.tatumUrlByNetworkId[network.id], {
|
|
70
|
+
httpHeaders: {
|
|
71
|
+
'x-api-key': apiKey,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
constructor(network, feeToken, mainnetApiKey, testnetApiKey) {
|
|
76
|
+
_TatumRpcBDSSolana_instances.add(this);
|
|
77
|
+
this.maxTimeToConfirmTransactionInMs = 1000 * 60;
|
|
78
|
+
_TatumRpcBDSSolana_network.set(this, void 0);
|
|
79
|
+
_TatumRpcBDSSolana_feeToken.set(this, void 0);
|
|
80
|
+
_TatumRpcBDSSolana_connection.set(this, void 0);
|
|
81
|
+
_TatumRpcBDSSolana_mainnetApiKey.set(this, void 0);
|
|
82
|
+
_TatumRpcBDSSolana_testnetApiKey.set(this, void 0);
|
|
83
|
+
_TatumRpcBDSSolana_functionByProgramIdAndMethod.set(this, {
|
|
84
|
+
[solanaSplSDK.TOKEN_PROGRAM_ID.toString()]: {
|
|
85
|
+
transferChecked: __classPrivateFieldGet(this, _TatumRpcBDSSolana_instances, "m", _TatumRpcBDSSolana_parseSplTransferCheckedInstruction).bind(this),
|
|
86
|
+
transfer: __classPrivateFieldGet(this, _TatumRpcBDSSolana_instances, "m", _TatumRpcBDSSolana_parseSplTransferInstruction).bind(this),
|
|
87
|
+
},
|
|
88
|
+
[web3_js_1.default.SystemProgram.programId.toString()]: {
|
|
89
|
+
transfer: __classPrivateFieldGet(this, _TatumRpcBDSSolana_instances, "m", _TatumRpcBDSSolana_parseSystemInstruction).bind(this),
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
__classPrivateFieldSet(this, _TatumRpcBDSSolana_network, network, "f");
|
|
93
|
+
__classPrivateFieldSet(this, _TatumRpcBDSSolana_feeToken, feeToken, "f");
|
|
94
|
+
__classPrivateFieldSet(this, _TatumRpcBDSSolana_mainnetApiKey, mainnetApiKey, "f");
|
|
95
|
+
__classPrivateFieldSet(this, _TatumRpcBDSSolana_testnetApiKey, testnetApiKey, "f");
|
|
96
|
+
__classPrivateFieldSet(this, _TatumRpcBDSSolana_connection, TatumRpcBDSSolana.getTatumConnection(network, BSSolanaHelper_1.BSSolanaHelper.isMainnet(network) ? mainnetApiKey : testnetApiKey), "f");
|
|
97
|
+
}
|
|
98
|
+
getFullTransactionsByAddress(_params) {
|
|
99
|
+
throw new Error('Method not implemented.');
|
|
100
|
+
}
|
|
101
|
+
exportFullTransactionsByAddress(_params) {
|
|
102
|
+
throw new Error('Method not implemented.');
|
|
103
|
+
}
|
|
104
|
+
getTransaction(txid) {
|
|
105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
var _a, _b;
|
|
107
|
+
const transaction = yield __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f").getParsedTransaction(txid, {
|
|
108
|
+
maxSupportedTransactionVersion: 0,
|
|
109
|
+
});
|
|
110
|
+
if (!transaction)
|
|
111
|
+
throw new Error('Transaction not found');
|
|
112
|
+
if (!transaction.blockTime)
|
|
113
|
+
throw new Error('Block time not found');
|
|
114
|
+
if (!transaction.meta)
|
|
115
|
+
throw new Error('Transaction meta not found');
|
|
116
|
+
const transfers = [];
|
|
117
|
+
const allInstructions = [
|
|
118
|
+
...transaction.transaction.message.instructions,
|
|
119
|
+
...((_b = (_a = transaction.meta.innerInstructions) === null || _a === void 0 ? void 0 : _a.flatMap(item => item.instructions)) !== null && _b !== void 0 ? _b : []),
|
|
120
|
+
].filter((item) => 'parsed' in item);
|
|
121
|
+
for (const instruction of allInstructions) {
|
|
122
|
+
try {
|
|
123
|
+
const transfer = yield __classPrivateFieldGet(this, _TatumRpcBDSSolana_instances, "m", _TatumRpcBDSSolana_parseInstruction).call(this, instruction, allInstructions);
|
|
124
|
+
if (transfer)
|
|
125
|
+
transfers.push(transfer);
|
|
126
|
+
}
|
|
127
|
+
catch (_c) {
|
|
128
|
+
/* empty */
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const feeBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(transaction.meta.fee, __classPrivateFieldGet(this, _TatumRpcBDSSolana_feeToken, "f").decimals);
|
|
132
|
+
const fee = blockchain_service_1.BSBigNumberHelper.toNumber(feeBn);
|
|
133
|
+
return {
|
|
134
|
+
block: transaction.slot,
|
|
135
|
+
hash: transaction.transaction.signatures[0],
|
|
136
|
+
notifications: [],
|
|
137
|
+
time: new Date(transaction.blockTime).getTime() / 1000,
|
|
138
|
+
transfers,
|
|
139
|
+
fee,
|
|
140
|
+
type: 'default',
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
getTransactionsByAddress(params) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
var _a;
|
|
147
|
+
const publicKey = new web3_js_1.default.PublicKey(params.address);
|
|
148
|
+
const signaturesResponse = yield __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f").getSignaturesForAddress(publicKey, {
|
|
149
|
+
limit: 15,
|
|
150
|
+
before: params.nextPageParams,
|
|
151
|
+
});
|
|
152
|
+
const transactions = [];
|
|
153
|
+
const promises = signaturesResponse.map((signatureResponse) => __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
const transaction = yield this.getTransaction(signatureResponse.signature);
|
|
155
|
+
transactions.push(transaction);
|
|
156
|
+
}));
|
|
157
|
+
yield Promise.allSettled(promises);
|
|
158
|
+
return {
|
|
159
|
+
transactions,
|
|
160
|
+
nextPageParams: signaturesResponse.length === 15 ? (_a = signaturesResponse.at(-1)) === null || _a === void 0 ? void 0 : _a.signature : undefined,
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
getContract(_contractHash) {
|
|
165
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
+
throw new Error('Method not implemented.');
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
getTokenInfo(tokenHash) {
|
|
170
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
171
|
+
if (tokenHash === BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN.hash) {
|
|
172
|
+
return BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN;
|
|
173
|
+
}
|
|
174
|
+
const token = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getMetaplexMetadata(tokenHash, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
175
|
+
if (!token || token.model === 'nft') {
|
|
176
|
+
throw new Error(`Token not found: ${tokenHash}`);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
symbol: token.currency.symbol,
|
|
180
|
+
name: token.name,
|
|
181
|
+
decimals: token.decimals,
|
|
182
|
+
hash: tokenHash,
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
getBalance(address) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
const publicKey = new web3_js_1.default.PublicKey(address);
|
|
189
|
+
const nativeBalance = yield __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f").getBalance(publicKey);
|
|
190
|
+
const splBalance = yield __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f").getParsedTokenAccountsByOwner(publicKey, {
|
|
191
|
+
programId: solanaSplSDK.TOKEN_PROGRAM_ID,
|
|
192
|
+
});
|
|
193
|
+
const nativeBalanceBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(nativeBalance, BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN.decimals);
|
|
194
|
+
const nativeBalanceAmount = blockchain_service_1.BSBigNumberHelper.toNumber(nativeBalanceBn);
|
|
195
|
+
const balances = [
|
|
196
|
+
{
|
|
197
|
+
amount: nativeBalanceAmount,
|
|
198
|
+
token: BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN,
|
|
199
|
+
},
|
|
200
|
+
];
|
|
201
|
+
const promises = splBalance.value.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
const token = yield this.getTokenInfo(item.account.data.parsed.info.mint);
|
|
203
|
+
const amountBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(item.account.data.parsed.info.tokenAmount.amount, token.decimals);
|
|
204
|
+
if (amountBn.isNaN() || amountBn.isLessThanOrEqualTo(0))
|
|
205
|
+
return;
|
|
206
|
+
const amount = blockchain_service_1.BSBigNumberHelper.toNumber(amountBn);
|
|
207
|
+
balances.push({
|
|
208
|
+
amount,
|
|
209
|
+
token,
|
|
210
|
+
});
|
|
211
|
+
}));
|
|
212
|
+
yield Promise.allSettled(promises);
|
|
213
|
+
return balances;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
getBlockHeight() {
|
|
217
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
218
|
+
return yield __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f").getBlockHeight();
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
getRpcList() {
|
|
222
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
223
|
+
const list = [];
|
|
224
|
+
const urls = BSSolanaConstants_1.BSSolanaConstants.RPC_LIST_BY_NETWORK_ID[__classPrivateFieldGet(this, _TatumRpcBDSSolana_network, "f").id];
|
|
225
|
+
if (!urls) {
|
|
226
|
+
throw new Error('RPC list not found');
|
|
227
|
+
}
|
|
228
|
+
const promises = urls.map(url => {
|
|
229
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
230
|
+
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
231
|
+
const timeout = setTimeout(() => {
|
|
232
|
+
resolve();
|
|
233
|
+
}, 5000);
|
|
234
|
+
try {
|
|
235
|
+
const connection = TatumRpcBDSSolana.getTatumConnection(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _TatumRpcBDSSolana_network, "f")), { url }), BSSolanaHelper_1.BSSolanaHelper.isMainnet(__classPrivateFieldGet(this, _TatumRpcBDSSolana_network, "f")) ? __classPrivateFieldGet(this, _TatumRpcBDSSolana_mainnetApiKey, "f") : __classPrivateFieldGet(this, _TatumRpcBDSSolana_testnetApiKey, "f"));
|
|
236
|
+
const timeStart = Date.now();
|
|
237
|
+
const height = yield connection.getBlockHeight();
|
|
238
|
+
const latency = Date.now() - timeStart;
|
|
239
|
+
list.push({
|
|
240
|
+
url,
|
|
241
|
+
height,
|
|
242
|
+
latency,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
catch (_a) {
|
|
246
|
+
/* empty */
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
resolve();
|
|
250
|
+
clearTimeout(timeout);
|
|
251
|
+
}
|
|
252
|
+
}));
|
|
253
|
+
});
|
|
254
|
+
yield Promise.allSettled(promises);
|
|
255
|
+
return list;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
exports.TatumRpcBDSSolana = TatumRpcBDSSolana;
|
|
260
|
+
_TatumRpcBDSSolana_network = new WeakMap(), _TatumRpcBDSSolana_feeToken = new WeakMap(), _TatumRpcBDSSolana_connection = new WeakMap(), _TatumRpcBDSSolana_mainnetApiKey = new WeakMap(), _TatumRpcBDSSolana_testnetApiKey = new WeakMap(), _TatumRpcBDSSolana_functionByProgramIdAndMethod = new WeakMap(), _TatumRpcBDSSolana_instances = new WeakSet(), _TatumRpcBDSSolana_parseSplTransferCheckedInstruction = function _TatumRpcBDSSolana_parseSplTransferCheckedInstruction(instruction, allInstructions) {
|
|
261
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
262
|
+
var _a;
|
|
263
|
+
const info = instruction.parsed.info;
|
|
264
|
+
if (!info.destination || !info.source || !info.mint) {
|
|
265
|
+
throw new Error('Unsupported instruction format');
|
|
266
|
+
}
|
|
267
|
+
const contractHash = info.mint;
|
|
268
|
+
const metaplex = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getMetaplexMetadata(contractHash, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
269
|
+
if (!metaplex) {
|
|
270
|
+
throw new Error('Metaplex metadata not found');
|
|
271
|
+
}
|
|
272
|
+
const toTokenAddress = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getSplAddress(info.destination, contractHash, allInstructions, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
273
|
+
if (!toTokenAddress) {
|
|
274
|
+
throw new Error('To account not found');
|
|
275
|
+
}
|
|
276
|
+
const to = toTokenAddress.toBase58();
|
|
277
|
+
const fromTokenAddress = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getSplAddress(info.source, contractHash, allInstructions, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
278
|
+
if (!fromTokenAddress) {
|
|
279
|
+
throw new Error('From account not found');
|
|
280
|
+
}
|
|
281
|
+
const from = fromTokenAddress.toBase58();
|
|
282
|
+
if ((metaplex === null || metaplex === void 0 ? void 0 : metaplex.model) === 'nft') {
|
|
283
|
+
if (!((_a = metaplex.collection) === null || _a === void 0 ? void 0 : _a.address)) {
|
|
284
|
+
throw new Error('Collection address not found');
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
type: 'nft',
|
|
288
|
+
from,
|
|
289
|
+
to,
|
|
290
|
+
tokenHash: contractHash,
|
|
291
|
+
collectionHash: metaplex.collection.address.toBase58(),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
const token = {
|
|
295
|
+
symbol: metaplex.currency.symbol,
|
|
296
|
+
name: metaplex.name,
|
|
297
|
+
decimals: metaplex.decimals,
|
|
298
|
+
hash: contractHash,
|
|
299
|
+
};
|
|
300
|
+
const amountBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(info.tokenAmount.amount, token.decimals);
|
|
301
|
+
const amount = blockchain_service_1.BSBigNumberHelper.toNumber(amountBn);
|
|
302
|
+
return {
|
|
303
|
+
type: 'token',
|
|
304
|
+
amount,
|
|
305
|
+
contractHash,
|
|
306
|
+
from,
|
|
307
|
+
to,
|
|
308
|
+
token,
|
|
309
|
+
};
|
|
310
|
+
});
|
|
311
|
+
}, _TatumRpcBDSSolana_parseSplTransferInstruction = function _TatumRpcBDSSolana_parseSplTransferInstruction(instruction, allInstructions) {
|
|
312
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
313
|
+
var _a;
|
|
314
|
+
const info = instruction.parsed.info;
|
|
315
|
+
if (!info.destination || !info.source || !info.amount) {
|
|
316
|
+
throw new Error('Unsupported instruction format');
|
|
317
|
+
}
|
|
318
|
+
const toTokenAccount = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getSplAccount(info.destination, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
319
|
+
if (!toTokenAccount) {
|
|
320
|
+
throw new Error('To account not found');
|
|
321
|
+
}
|
|
322
|
+
const contractHash = toTokenAccount.mint.toBase58();
|
|
323
|
+
const metaplex = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getMetaplexMetadata(contractHash, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
324
|
+
if (!metaplex) {
|
|
325
|
+
throw new Error('Metaplex metadata not found');
|
|
326
|
+
}
|
|
327
|
+
let to;
|
|
328
|
+
if (info.destination === toTokenAccount.address.toBase58()) {
|
|
329
|
+
const toTokenAddress = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getSplAddress(info.destination, contractHash, allInstructions, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
330
|
+
if (!toTokenAddress) {
|
|
331
|
+
throw new Error('To account not found');
|
|
332
|
+
}
|
|
333
|
+
to = toTokenAddress.toBase58();
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
to = toTokenAccount.address.toBase58();
|
|
337
|
+
}
|
|
338
|
+
const fromTokenAddress = yield BSSolanaCachedMethodsHelper_1.BSSolanaCachedMethodsHelper.getSplAddress(info.source, contractHash, allInstructions, __classPrivateFieldGet(this, _TatumRpcBDSSolana_connection, "f"));
|
|
339
|
+
if (!fromTokenAddress) {
|
|
340
|
+
throw new Error('From account not found');
|
|
341
|
+
}
|
|
342
|
+
const from = fromTokenAddress.toBase58();
|
|
343
|
+
if ((metaplex === null || metaplex === void 0 ? void 0 : metaplex.model) === 'nft') {
|
|
344
|
+
if (!((_a = metaplex.collection) === null || _a === void 0 ? void 0 : _a.address)) {
|
|
345
|
+
throw new Error('Collection address not found');
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
type: 'nft',
|
|
349
|
+
from,
|
|
350
|
+
to,
|
|
351
|
+
collectionHash: metaplex.collection.address.toBase58(),
|
|
352
|
+
tokenHash: contractHash,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const token = {
|
|
356
|
+
symbol: metaplex.currency.symbol,
|
|
357
|
+
name: metaplex.name,
|
|
358
|
+
decimals: metaplex.decimals,
|
|
359
|
+
hash: contractHash,
|
|
360
|
+
};
|
|
361
|
+
const amountBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(info.tokenAmount.amount, token.decimals);
|
|
362
|
+
const amount = blockchain_service_1.BSBigNumberHelper.toNumber(amountBn);
|
|
363
|
+
return {
|
|
364
|
+
type: 'token',
|
|
365
|
+
amount,
|
|
366
|
+
contractHash,
|
|
367
|
+
from,
|
|
368
|
+
to,
|
|
369
|
+
token,
|
|
370
|
+
};
|
|
371
|
+
});
|
|
372
|
+
}, _TatumRpcBDSSolana_parseSystemInstruction = function _TatumRpcBDSSolana_parseSystemInstruction(instruction) {
|
|
373
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
374
|
+
const info = instruction.parsed.info;
|
|
375
|
+
const method = instruction.parsed.type;
|
|
376
|
+
if (info.lamports === undefined || info.source === undefined || method !== 'transfer' || !info.destination) {
|
|
377
|
+
throw new Error('Unsupported instruction format');
|
|
378
|
+
}
|
|
379
|
+
const amountBn = blockchain_service_1.BSBigNumberHelper.fromDecimals(info.lamports, BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN.decimals);
|
|
380
|
+
const amount = blockchain_service_1.BSBigNumberHelper.toNumber(amountBn);
|
|
381
|
+
return {
|
|
382
|
+
type: 'token',
|
|
383
|
+
amount,
|
|
384
|
+
from: info.source,
|
|
385
|
+
to: info.destination,
|
|
386
|
+
contractHash: BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN.hash,
|
|
387
|
+
token: BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN,
|
|
388
|
+
};
|
|
389
|
+
});
|
|
390
|
+
}, _TatumRpcBDSSolana_parseInstruction = function _TatumRpcBDSSolana_parseInstruction(instruction, allInstructions) {
|
|
391
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
392
|
+
var _a;
|
|
393
|
+
if (!instruction.parsed.type || !instruction.parsed.info) {
|
|
394
|
+
throw new Error('Unsupported instruction format');
|
|
395
|
+
}
|
|
396
|
+
const programId = instruction.programId.toString();
|
|
397
|
+
const method = instruction.parsed.type;
|
|
398
|
+
const func = (_a = __classPrivateFieldGet(this, _TatumRpcBDSSolana_functionByProgramIdAndMethod, "f")[programId]) === null || _a === void 0 ? void 0 : _a[method];
|
|
399
|
+
if (func) {
|
|
400
|
+
return yield func(instruction, allInstructions);
|
|
401
|
+
}
|
|
402
|
+
throw new Error('Unsupported instruction');
|
|
403
|
+
});
|
|
404
|
+
};
|
|
405
|
+
TatumRpcBDSSolana.tatumUrlByNetworkId = {
|
|
406
|
+
'mainnet-beta': 'https://solana-mainnet.gateway.tatum.io/',
|
|
407
|
+
devnet: 'https://solana-devnet.gateway.tatum.io',
|
|
408
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CryptoCompareEDS, ExchangeDataService, GetTokenPriceHistoryParams, GetTokenPricesParams, Network, TokenPricesHistoryResponse, TokenPricesResponse } from '@cityofzion/blockchain-service';
|
|
2
|
+
import { BSSolanaNetworkId } from '../../constants/BSSolanaConstants';
|
|
3
|
+
export declare class MoralisEDSSolana extends CryptoCompareEDS implements ExchangeDataService {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(network: Network<BSSolanaNetworkId>, apiKey: string);
|
|
6
|
+
getTokenPrices({ tokens }: GetTokenPricesParams): Promise<TokenPricesResponse[]>;
|
|
7
|
+
getTokenPriceHistory(params: GetTokenPriceHistoryParams): Promise<TokenPricesHistoryResponse[]>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
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 __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
14
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
15
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
16
|
+
};
|
|
17
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
18
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
19
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
20
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
21
|
+
};
|
|
22
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
|
+
};
|
|
25
|
+
var _MoralisEDSSolana_network, _MoralisEDSSolana_client, _MoralisEDSSolana_pairAddressCache;
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.MoralisEDSSolana = void 0;
|
|
28
|
+
const blockchain_service_1 = require("@cityofzion/blockchain-service");
|
|
29
|
+
const BSSolanaHelper_1 = require("../../helpers/BSSolanaHelper");
|
|
30
|
+
const BSSolanaConstants_1 = require("../../constants/BSSolanaConstants");
|
|
31
|
+
const axios_1 = __importDefault(require("axios"));
|
|
32
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
33
|
+
class MoralisEDSSolana extends blockchain_service_1.CryptoCompareEDS {
|
|
34
|
+
constructor(network, apiKey) {
|
|
35
|
+
super();
|
|
36
|
+
_MoralisEDSSolana_network.set(this, void 0);
|
|
37
|
+
_MoralisEDSSolana_client.set(this, void 0);
|
|
38
|
+
_MoralisEDSSolana_pairAddressCache.set(this, new Map());
|
|
39
|
+
__classPrivateFieldSet(this, _MoralisEDSSolana_network, network, "f");
|
|
40
|
+
__classPrivateFieldSet(this, _MoralisEDSSolana_client, axios_1.default.create({
|
|
41
|
+
baseURL: 'https://solana-gateway.moralis.io',
|
|
42
|
+
headers: {
|
|
43
|
+
'X-API-Key': apiKey,
|
|
44
|
+
},
|
|
45
|
+
}), "f");
|
|
46
|
+
}
|
|
47
|
+
getTokenPrices(_a) {
|
|
48
|
+
return __awaiter(this, arguments, void 0, function* ({ tokens }) {
|
|
49
|
+
if (!BSSolanaHelper_1.BSSolanaHelper.isMainnet(__classPrivateFieldGet(this, _MoralisEDSSolana_network, "f")))
|
|
50
|
+
throw new Error('Exchange is only available on mainnet');
|
|
51
|
+
const promises = tokens.map((token) => __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
const hash = token.hash === BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN.hash ? BSSolanaConstants_1.BSSolanaConstants.NATIVE_WRAPPED_HASH : token.hash;
|
|
53
|
+
let usdPrice = 0;
|
|
54
|
+
try {
|
|
55
|
+
const priceResponse = yield __classPrivateFieldGet(this, _MoralisEDSSolana_client, "f").get(`token/mainnet/${hash}/price`);
|
|
56
|
+
usdPrice = priceResponse.data.usdPrice;
|
|
57
|
+
__classPrivateFieldGet(this, _MoralisEDSSolana_pairAddressCache, "f").set(token.hash, priceResponse.data.pairAddress);
|
|
58
|
+
}
|
|
59
|
+
catch (_a) {
|
|
60
|
+
/* empty */
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
token,
|
|
64
|
+
usdPrice,
|
|
65
|
+
};
|
|
66
|
+
}));
|
|
67
|
+
return yield Promise.all(promises);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
getTokenPriceHistory(params) {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
if (!BSSolanaHelper_1.BSSolanaHelper.isMainnet(__classPrivateFieldGet(this, _MoralisEDSSolana_network, "f")))
|
|
73
|
+
throw new Error('Exchange is only available on mainnet');
|
|
74
|
+
const tokenHash = params.token.hash === BSSolanaConstants_1.BSSolanaConstants.NATIVE_TOKEN.hash
|
|
75
|
+
? BSSolanaConstants_1.BSSolanaConstants.NATIVE_WRAPPED_HASH
|
|
76
|
+
: params.token.hash;
|
|
77
|
+
let pairAddress = __classPrivateFieldGet(this, _MoralisEDSSolana_pairAddressCache, "f").get(tokenHash);
|
|
78
|
+
if (!pairAddress) {
|
|
79
|
+
const priceResponse = yield __classPrivateFieldGet(this, _MoralisEDSSolana_client, "f").get(`token/mainnet/${tokenHash}/price`);
|
|
80
|
+
__classPrivateFieldGet(this, _MoralisEDSSolana_pairAddressCache, "f").set(tokenHash, priceResponse.data.pairAddress);
|
|
81
|
+
pairAddress = priceResponse.data.pairAddress;
|
|
82
|
+
}
|
|
83
|
+
const toDate = (0, dayjs_1.default)().unix();
|
|
84
|
+
const fromDate = (0, dayjs_1.default)().subtract(params.limit, params.type).unix();
|
|
85
|
+
const pricesHistoryResponse = yield __classPrivateFieldGet(this, _MoralisEDSSolana_client, "f").get(`token/mainnet/pairs/${pairAddress}/ohlcv`, {
|
|
86
|
+
params: {
|
|
87
|
+
timeframe: params.type === 'day' ? '1d' : '1h',
|
|
88
|
+
currency: 'usd',
|
|
89
|
+
limit: params.limit,
|
|
90
|
+
toDate,
|
|
91
|
+
fromDate,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
const pricesHistory = pricesHistoryResponse.data.result.map(price => ({
|
|
95
|
+
timestamp: (0, dayjs_1.default)(price.timestamp).unix(),
|
|
96
|
+
token: params.token,
|
|
97
|
+
usdPrice: price.close,
|
|
98
|
+
}));
|
|
99
|
+
return pricesHistory;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.MoralisEDSSolana = MoralisEDSSolana;
|
|
104
|
+
_MoralisEDSSolana_network = new WeakMap(), _MoralisEDSSolana_client = new WeakMap(), _MoralisEDSSolana_pairAddressCache = new WeakMap();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BuildNftUrlParams, ExplorerService, Network, TokenService } from '@cityofzion/blockchain-service';
|
|
2
|
+
import { BSSolanaNetworkId } from '../../constants/BSSolanaConstants';
|
|
3
|
+
export declare class SolScanESSolana implements ExplorerService {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(network: Network<BSSolanaNetworkId>, tokenService: TokenService);
|
|
6
|
+
buildTransactionUrl(hash: string): string;
|
|
7
|
+
buildContractUrl(contractHash: string): string;
|
|
8
|
+
buildNftUrl({ tokenHash }: BuildNftUrlParams): string;
|
|
9
|
+
getAddressTemplateUrl(): string | undefined;
|
|
10
|
+
getTxTemplateUrl(): string;
|
|
11
|
+
getNftTemplateUrl(): string;
|
|
12
|
+
getContractTemplateUrl(): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _SolScanESSolana_baseUrl, _SolScanESSolana_queryParams, _SolScanESSolana_tokenService;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SolScanESSolana = void 0;
|
|
16
|
+
const BSSolanaHelper_1 = require("../../helpers/BSSolanaHelper");
|
|
17
|
+
class SolScanESSolana {
|
|
18
|
+
constructor(network, tokenService) {
|
|
19
|
+
_SolScanESSolana_baseUrl.set(this, 'https://solscan.io');
|
|
20
|
+
_SolScanESSolana_queryParams.set(this, '');
|
|
21
|
+
_SolScanESSolana_tokenService.set(this, void 0);
|
|
22
|
+
if (!BSSolanaHelper_1.BSSolanaHelper.isMainnet(network)) {
|
|
23
|
+
__classPrivateFieldSet(this, _SolScanESSolana_queryParams, `?cluster=${network.id}`, "f");
|
|
24
|
+
}
|
|
25
|
+
__classPrivateFieldSet(this, _SolScanESSolana_tokenService, tokenService, "f");
|
|
26
|
+
}
|
|
27
|
+
buildTransactionUrl(hash) {
|
|
28
|
+
return `${__classPrivateFieldGet(this, _SolScanESSolana_baseUrl, "f")}/tx/${__classPrivateFieldGet(this, _SolScanESSolana_tokenService, "f").normalizeHash(hash)}${__classPrivateFieldGet(this, _SolScanESSolana_queryParams, "f")}`;
|
|
29
|
+
}
|
|
30
|
+
buildContractUrl(contractHash) {
|
|
31
|
+
return `${__classPrivateFieldGet(this, _SolScanESSolana_baseUrl, "f")}/token/${__classPrivateFieldGet(this, _SolScanESSolana_tokenService, "f").normalizeHash(contractHash)}${__classPrivateFieldGet(this, _SolScanESSolana_queryParams, "f")}`;
|
|
32
|
+
}
|
|
33
|
+
buildNftUrl({ tokenHash }) {
|
|
34
|
+
return this.buildContractUrl(tokenHash);
|
|
35
|
+
}
|
|
36
|
+
getAddressTemplateUrl() {
|
|
37
|
+
return `${__classPrivateFieldGet(this, _SolScanESSolana_baseUrl, "f")}/account/{address}${__classPrivateFieldGet(this, _SolScanESSolana_queryParams, "f")}`;
|
|
38
|
+
}
|
|
39
|
+
getTxTemplateUrl() {
|
|
40
|
+
return `${__classPrivateFieldGet(this, _SolScanESSolana_baseUrl, "f")}/tx/{txId}${__classPrivateFieldGet(this, _SolScanESSolana_queryParams, "f")}`;
|
|
41
|
+
}
|
|
42
|
+
getNftTemplateUrl() {
|
|
43
|
+
return `${__classPrivateFieldGet(this, _SolScanESSolana_baseUrl, "f")}/token/{tokenHash}${__classPrivateFieldGet(this, _SolScanESSolana_queryParams, "f")}`;
|
|
44
|
+
}
|
|
45
|
+
getContractTemplateUrl() {
|
|
46
|
+
return `${__classPrivateFieldGet(this, _SolScanESSolana_baseUrl, "f")}/token/{hash}${__classPrivateFieldGet(this, _SolScanESSolana_queryParams, "f")}`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.SolScanESSolana = SolScanESSolana;
|
|
50
|
+
_SolScanESSolana_baseUrl = new WeakMap(), _SolScanESSolana_queryParams = new WeakMap(), _SolScanESSolana_tokenService = new WeakMap();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Account, LedgerService, LedgerServiceEmitter, GetLedgerTransport, UntilIndexRecord } from '@cityofzion/blockchain-service';
|
|
2
|
+
import { BSSolana } from '../../BSSolana';
|
|
3
|
+
import Transport from '@ledgerhq/hw-transport';
|
|
4
|
+
import solanaSDK from '@solana/web3.js';
|
|
5
|
+
export declare class Web3LedgerServiceSolana<BSName extends string = string> implements LedgerService<BSName> {
|
|
6
|
+
#private;
|
|
7
|
+
emitter: LedgerServiceEmitter;
|
|
8
|
+
getLedgerTransport?: GetLedgerTransport<BSName>;
|
|
9
|
+
constructor(blockchainService: BSSolana<BSName>, getLedgerTransport?: GetLedgerTransport<BSName>);
|
|
10
|
+
getAccounts(transport: Transport, untilIndexByBlockchainService?: UntilIndexRecord<BSName>): Promise<Account<BSName>[]>;
|
|
11
|
+
getAccount(transport: Transport, index: number): Promise<Account<BSName>>;
|
|
12
|
+
signTransaction(transport: Transport, transaction: solanaSDK.Transaction, account: Account<BSName>): Promise<Buffer<ArrayBufferLike>>;
|
|
13
|
+
}
|