UNPKG

test-ic-wallet-middleware-icrc

Version:
239 lines (238 loc) 11.3 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TransactionRepository = void 0; const ledger_icp_1 = require("@dfinity/ledger-icp"); const common_1 = require("@ic-wallet-middleware/common"); const transactionsRepositoryError_1 = require("../../../errors/transactionsRepositoryError"); const types_1 = require("../../../types"); const enums_1 = require("../../../types/enums"); const indexWrapper_1 = require("../../../wrappers/icrc/indexWrapper/indexWrapper"); const typedi_1 = require("typedi"); const milliPerSecond = 1000000; let TransactionRepository = class TransactionRepository { identifierService; constructor(identifierService) { this.identifierService = identifierService; } async getIcpListTransaction(asset, param) { const skip = asset.pageInfo.nextPageKey ? Number(asset.pageInfo.nextPageKey) : 0; if (Number.isNaN(skip)) { throw new transactionsRepositoryError_1.TransactionsRepositoryError("get.icp.list.transaction.invalid.nextPageKey", "Invalid nextPageKey"); } let result = []; for (const subAccountId of asset.subAccountIds) { let subAccount = ledger_icp_1.SubAccount.fromBytes(subAccountId.toUint8Array()); const accountIdentifier = ledger_icp_1.AccountIdentifier.fromPrincipal({ principal: this.identifierService.getPrincipal(), subAccount: subAccount, }); try { const response = await fetch(`${param.url}/search/transactions`, { method: "POST", body: JSON.stringify({ network_identifier: { blockchain: param.blockchain, network: param.network, }, account_identifier: { address: accountIdentifier.toHex(), }, offset: skip, limit: asset.pageInfo.take }), headers: { "Content-Type": "application/json", Accept: "*/*", }, }).catch(); if (!response.ok) throw Error(`${response.statusText}`); const { transactions } = await response.json(); const trans = transactions.map(({ transaction, block_identifier }) => this.formatIcpTransaction(accountIdentifier.toHex(), transaction, block_identifier.hash, param.canisterId)); result = result.concat(trans); if (result.length >= asset.pageInfo.take) { result = result.slice(0, asset.pageInfo.take); break; } } catch (e) { throw new transactionsRepositoryError_1.TransactionsRepositoryError("get.icp.list.transaction.error", e.message); } } const hasNext = result.length == asset.pageInfo.take; let nextPageKey = common_1.PageResultEmptyKey; if (hasNext) { nextPageKey = (asset.pageInfo.take + skip).toString(); } return { transactions: result, pageResult: { hasNext: hasNext, nextPageKey: nextPageKey } }; } async getIcrcListTransactionByAsset(asset) { let result = []; for (const subAccountId of asset.subAccountIds) { const indexWrapper = indexWrapper_1.IndexWrapper.create(asset.indexAsset); const transactions = await indexWrapper.getTransactions(this.identifierService.getPrincipal(), subAccountId, asset.pageInfo); const tran = transactions.map((t) => this.formatCkBTCTransaction(t, asset.indexAsset, asset.symbol, subAccountId)); result = result.concat(tran); if (result.length >= asset.pageInfo.take) { result = result.slice(0, asset.pageInfo.take); break; } } ; const hasNext = result.length == asset.pageInfo.take; let nextPageKey = common_1.PageResultEmptyKey; if (hasNext && asset.pageInfo.take > 0) { nextPageKey = result[result.length - 1].idx; } return { transactions: result, pageResult: { hasNext: hasNext, nextPageKey: nextPageKey } }; } formatIcpTransaction(accountId, rosettaTransaction, blockHash, canisterId) { const model = { status: enums_1.OperationStatusEnum.COMPLETED, hash: rosettaTransaction.transaction_identifier.hash + "-" + blockHash, timestamp: Math.floor(rosettaTransaction.metadata.timestamp / milliPerSecond) }; rosettaTransaction.operations.forEach((operation, i) => { const value = BigInt(operation.amount.value); const amount = value; if (operation.type === enums_1.OperationTypeEnum.FEE) { model.fee = amount; return; } if (value > BigInt(0)) { model.to = operation.account.address; } else if (value < BigInt(0)) { model.from = operation.account.address; } else { if (i === 0) { model.from = operation.account.address; } if (i === 1) { model.to = operation.account.address; } } if (model.status === enums_1.OperationStatusEnum.COMPLETED && operation.status !== enums_1.OperationStatusEnum.COMPLETED) { model.status = operation.status; } model.type = model.to === accountId ? enums_1.TransactionTypeEnum.RECEIVE : enums_1.TransactionTypeEnum.SEND; model.amount = amount; model.canisterId = canisterId; model.idx = rosettaTransaction.metadata.block_height.toString(); model.symbol = operation.amount.currency.symbol; }); return model; } formatCkBTCTransaction(transactionWithId, canisterId, symbol, subAccountId) { const transaction = transactionWithId.transaction; const model = { timestamp: Math.floor(Number(transaction.timestamp) / milliPerSecond), status: enums_1.OperationStatusEnum.COMPLETED, type: enums_1.TransactionTypeEnum.NONE, kind: transaction.kind }; switch (transaction.kind) { case "mint": transaction.mint.forEach((item) => { // Get Tx data from Mint record const amount = item.amount; this.setTransactionBaseField(model, transactionWithId, canisterId, symbol, amount); model.to = item.to.owner.toString(); model.toSub = this.getSubAccount(item.to.subaccount); // Get AccountIdentifier of Receiver model.identityTo = this.getAccountIdentifier(item.to.subaccount, item.to.owner); model.type = enums_1.TransactionTypeEnum.RECEIVE; }); break; case "burn": transaction.burn.forEach((item) => { // Get Tx data from Burn record const amount = item.amount; this.setTransactionBaseField(model, transactionWithId, canisterId, symbol, amount); model.from = item.from.owner.toString(); model.fromSub = this.getSubAccount(item.from.subaccount); // Get AccountIdentifier of Sender model.identityFrom = this.getAccountIdentifier(item.from.subaccount, item.from.owner); model.type = enums_1.TransactionTypeEnum.SEND; }); break; default: transaction.transfer.forEach((item) => { // Get Tx data from transfer record const amount = item.amount; this.setTransactionBaseField(model, transactionWithId, canisterId, symbol, amount); model.to = item.to.owner.toString(); model.toSub = this.getSubAccount(item.to.subaccount); model.from = item.from.owner.toString(); model.fromSub = this.getSubAccount(item.from.subaccount); const subCheck = subAccountId; if (model.from === this.identifierService.getPrincipalStr() && model.fromSub.equals(subCheck)) { model.type = enums_1.TransactionTypeEnum.SEND; } else { model.type = enums_1.TransactionTypeEnum.RECEIVE; } // Get AccountIdentifier of Receiver model.identityTo = this.getAccountIdentifier(item.to.subaccount, item.to.owner); // Get AccountIdentifier of Sender model.identityFrom = this.getAccountIdentifier(item.from.subaccount, item.from.owner); }); break; } return model; } getAccountIdentifier(subAccount, owner) { let subAcc = undefined; try { subAcc = ledger_icp_1.SubAccount.fromBytes(subAccount[0]); } catch { subAcc = undefined; } const identity = ledger_icp_1.AccountIdentifier.fromPrincipal({ principal: owner, subAccount: subAcc, }).toHex(); return identity; } getSubAccount(subaccount) { return subaccount.length > 0 ? types_1.SubAccountId.parseFromUint8Array(subaccount[0]) : types_1.SubAccountId.parseFromString("0x0"); } setTransactionBaseField(model, transactionWithId, canisterId, symbol, amount) { model.canisterId = canisterId; model.symbol = symbol; model.amount = amount; model.idx = transactionWithId.id.toString(); } }; exports.TransactionRepository = TransactionRepository; exports.TransactionRepository = TransactionRepository = __decorate([ (0, typedi_1.Service)(), __metadata("design:paramtypes", [common_1.IdentifierService]) ], TransactionRepository);