From 2c6b79b96ad06f0f4a558732e6b05aa5131b31d3 Mon Sep 17 00:00:00 2001 From: Anni Piragauta Date: Fri, 21 Feb 2025 12:01:24 -0500 Subject: [PATCH 1/2] fix: receives values form the app as bigInt string an save them as decimal legible values --- package-lock.json | 87 +++++++++++++++++ package.json | 1 + .../unit/register.controller.unit.ts | 40 ++++---- .../services/flyover-service.service.unit.ts | 38 ++++++++ src/__tests__/unit/utils/parse-units.unit.ts | 21 +++++ src/models/app-tx.model.ts | 8 +- src/models/flyover-status.model.ts | 4 +- src/models/quote-db.model.ts | 40 ++++---- src/models/register-payload.model.ts | 16 ++-- src/services/flyover.service.ts | 94 +++++++------------ src/services/register.service.ts | 20 ++-- src/utils/parseUnits.ts | 10 ++ 12 files changed, 259 insertions(+), 120 deletions(-) create mode 100644 src/__tests__/unit/services/flyover-service.service.unit.ts create mode 100644 src/__tests__/unit/utils/parse-units.unit.ts create mode 100644 src/utils/parseUnits.ts diff --git a/package-lock.json b/package-lock.json index 9a2df64a..d7ce5d62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "bridge-transaction-parser": "git+https://github.com/rsksmart/bridge-transaction-parser.git#v0.5.0-beta", "bs58": "^5.0.0", "dotenv": "^8.6.0", + "ethers": "^6.13.5", "jssha": "^3.2.0", "log4js": "^6.6.1", "loopback-connector-kv-redis": "^4.0.0", @@ -65,6 +66,11 @@ "node": ">=0.10.0" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -2643,6 +2649,11 @@ "node": ">=6.0" } }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, "node_modules/agent-base": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", @@ -4917,6 +4928,77 @@ "node": ">=10.0.0" } }, + "node_modules/ethers": { + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", + "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -11332,6 +11414,11 @@ "node": ">=14.0" } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/package.json b/package.json index 96909edf..3a834e42 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "bridge-transaction-parser": "git+https://github.com/rsksmart/bridge-transaction-parser.git#v0.5.0-beta", "bs58": "^5.0.0", "dotenv": "^8.6.0", + "ethers": "^6.13.5", "jssha": "^3.2.0", "log4js": "^6.6.1", "loopback-connector-kv-redis": "^4.0.0", diff --git a/src/__tests__/unit/register.controller.unit.ts b/src/__tests__/unit/register.controller.unit.ts index cd82d4ce..e51f04d8 100644 --- a/src/__tests__/unit/register.controller.unit.ts +++ b/src/__tests__/unit/register.controller.unit.ts @@ -18,42 +18,42 @@ describe('RegisterController', () => { let payload = new RegisterPayload({ txHash: '0x', type: constants.TX_TYPE_PEGIN, - value: 0.005, + value: '5000000000000000', wallet: 'liquality', - fee: 0.000001, + fee: '1000000000000', }); let pegoutPayload = new RegisterPayload({ txHash: '0xb', type: constants.TX_TYPE_PEGOUT, - value: 0.004, + value: '4000000000000000', wallet: 'liquality', - fee: 0.000002, + fee: '2000000000000', }); let flyoverPayload = new RegisterPayload({ txHash: '0xc', type: constants.TX_TYPE_PEGOUT, - value: 0.005, + value: '5000000000000000', wallet: 'wallet', - fee: 0.000001, + fee: '1000000000000', provider: 'test provider', details: { - blocksToCompleteTransaction: 2, + blocksToCompleteTransaction: '2', }, quote: { - callFeeOnWei: 800n, + callFeeOnWei: '800', depositAddr: "testDeposit", - depositConfirmations: 200, - depositDateLimit: 49800, - expireBlocks: 100, - expireDate: 49850, - productFeeAmountOnWei: 6300n, - transferConfirmations: 80, - transferTime: 50600, - valueOnWei: 18450n, - agreementTimestamp: 1620000000, - gasFeeOnWei: 1000000000000000000n, - nonce: 1n, - penaltyFeeOnWei: 1000000000000000000n, + depositConfirmations: '200', + depositDateLimit: '49800', + expireBlocks: '100', + expireDate: '49850', + productFeeAmountOnWei: '6300', + transferConfirmations: '80', + transferTime: '50600', + valueOnWei: '18450', + agreementTimestamp: '1620000000', + gasFeeOnWei: '1000000000000000000', + nonce: '1000000000000000000', + penaltyFeeOnWei: '1000000000000000000', btcRefundAddress: "testBtcRefund", lbcAddress: "testLbc", lpBtcAddress: "testLpBtc", diff --git a/src/__tests__/unit/services/flyover-service.service.unit.ts b/src/__tests__/unit/services/flyover-service.service.unit.ts new file mode 100644 index 00000000..739557b2 --- /dev/null +++ b/src/__tests__/unit/services/flyover-service.service.unit.ts @@ -0,0 +1,38 @@ +// import { expect } from '@loopback/testlab'; +// import { FlyoverService } from '../../../services/flyover.service'; +// import { RegisterPayload } from '../../../models/register-payload.model'; +// import { FlyoverStatusModel } from '../../../models/flyover-status.model'; +// import { RskNodeService } from '../../../services/rsk-node.service'; +// import sinon from 'sinon'; + +// describe('Service: FlyoverService', () => { +// let flyoverService: FlyoverService; +// let rskNodeService: RskNodeService; + +// beforeEach(() => { +// rskNodeService = new RskNodeService(); +// flyoverService = new FlyoverService(); +// }); + +// afterEach(() => { +// sinon.restore(); +// }); +// describe('Service: FlyoverService', () => { +// it('should register a pegin native transaction successfully', async () => { +// const mockBlockNumber = 1000; +// sinon.stub(rskNodeService, 'getBlockNumber').resolves(mockBlockNumber); +// sinon.stub(flyoverService, 'set').resolves(true); + +// const payload: RegisterPayload = { +// "txHash": "0x807f14318a2f4bc62ae3a14370c243087464740fb2f5b16763f2fb1635708bb4", +// "type": "pegout", +// "value": "8000000000000000", +// "wallet": "Metamask", +// "btcEstimatedFee": "745632", +// "rskGas": "234858360000" +// }; + +// const result = await flyoverService.register(payload); +// expect(result).to.be.true(); +// }); +// }); diff --git a/src/__tests__/unit/utils/parse-units.unit.ts b/src/__tests__/unit/utils/parse-units.unit.ts new file mode 100644 index 00000000..b186cc55 --- /dev/null +++ b/src/__tests__/unit/utils/parse-units.unit.ts @@ -0,0 +1,21 @@ +import {stringWeiToDecimalString, stringSatoshiToDecimalString} from '../../../utils/parseUnits'; +import {expect} from '@loopback/testlab'; + +describe('ParseUnits', () => { + it('should get the decimal string value of a satoshi string', () => { + const stringValueInSatoshis = "1596"; + expect(stringSatoshiToDecimalString(stringValueInSatoshis)).to.be.eql("0.00001596"); + }); + it('should get the decimal string value of a wei string', () => { + const stringValueInWei = "79040000000000"; + expect(stringWeiToDecimalString(stringValueInWei)).to.be.eql("0.00007904"); + }); + it('should return zero string value of a satoshi string 0', () => { + const stringValueInSatoshis = "0"; + expect(stringSatoshiToDecimalString(stringValueInSatoshis)).to.be.eql("0"); + }); + it('should return zero string value of a wei string 0', () => { + const stringValueInWei = "79040000000000"; + expect(stringWeiToDecimalString(stringValueInWei)).to.be.eql("0"); + }); +}); \ No newline at end of file diff --git a/src/models/app-tx.model.ts b/src/models/app-tx.model.ts index 31c4b038..f4dd66fb 100644 --- a/src/models/app-tx.model.ts +++ b/src/models/app-tx.model.ts @@ -4,12 +4,12 @@ export class AppTxModel implements SearchableModel { txHash: string; type: string; creationDate: Date; - value: number; + value: string; wallet: string; addressType: string; - fee: number; - rskGas: number; - btcEstimatedFee: number; + fee: string; + rskGas: string; + btcEstimatedFee: string; provider: string; getId() { diff --git a/src/models/flyover-status.model.ts b/src/models/flyover-status.model.ts index 61cc7d82..e6d7826a 100644 --- a/src/models/flyover-status.model.ts +++ b/src/models/flyover-status.model.ts @@ -9,8 +9,8 @@ export class FlyoverStatusModel implements SearchableModel { txHash: string; type: string; date: Date; - amount: number; - fee: number; + amount: string; + fee: string; blockToBeFinished: number; senderAddress: string; recipientAddress: string; diff --git a/src/models/quote-db.model.ts b/src/models/quote-db.model.ts index 079ee3a1..3c244461 100644 --- a/src/models/quote-db.model.ts +++ b/src/models/quote-db.model.ts @@ -1,8 +1,8 @@ export interface BaseQuoteDbModel { - agreementTimestamp: number; - gasFeeOnWei: bigint; - nonce: bigint; - penaltyFeeOnWei: bigint; + agreementTimestamp: string; + gasFeeOnWei: string; + nonce: string; + penaltyFeeOnWei: string; btcRefundAddress: string; lbcAddress: string; lpBtcAddress: string; @@ -11,30 +11,30 @@ export interface BaseQuoteDbModel { } export interface PeginQuoteDbModel extends BaseQuoteDbModel { - callFeeOnSatoshi: bigint; + callFeeOnSatoshi: string; callOnRegister: boolean; - confirmations: number; + confirmations: string; contractAddr: string; data: string; fedBTCAddr: string; - gasLimit: bigint; - lpCallTime: number; - productFeeAmountOnSatoshi: bigint; - timeForDepositInSeconds: number; - valueOnSatoshi: bigint; + gasLimit: string; + lpCallTime: string; + productFeeAmountOnSatoshi: string; + timeForDepositInSeconds: string; + valueOnSatoshi: string; } export interface PegoutQuoteDbModel extends BaseQuoteDbModel { - callFeeOnWei: bigint; + callFeeOnWei: string; depositAddr: string; - depositConfirmations: number; - depositDateLimit: number; - expireBlocks: number; - expireDate: number; - productFeeAmountOnWei: bigint; - transferConfirmations: number; - transferTime: number; - valueOnWei: bigint; + depositConfirmations: string; + depositDateLimit: string; + expireBlocks: string; + expireDate: string; + productFeeAmountOnWei: string; + transferConfirmations: string; + transferTime: string; + valueOnWei: string; } export type QuoteDbModel = Partial; \ No newline at end of file diff --git a/src/models/register-payload.model.ts b/src/models/register-payload.model.ts index 4dbea76c..d25359a4 100644 --- a/src/models/register-payload.model.ts +++ b/src/models/register-payload.model.ts @@ -16,10 +16,10 @@ export class RegisterPayload extends Model { type: string; @property({ - type: 'number', + type: 'string', required: true, }) - value: number; + value: string; @property({ type: 'string', @@ -33,19 +33,19 @@ export class RegisterPayload extends Model { addressType?: string; @property({ - type: 'number', + type: 'string', }) - fee?: number; + fee?: string; @property({ - type: 'number', + type: 'string', }) - rskGas?: number; + rskGas?: string; @property({ - type: 'number', + type: 'string', }) - btcEstimatedFee?: number; + btcEstimatedFee?: string; @property({ type: 'string', diff --git a/src/services/flyover.service.ts b/src/services/flyover.service.ts index b06f90fa..ebfcb71a 100644 --- a/src/services/flyover.service.ts +++ b/src/services/flyover.service.ts @@ -1,45 +1,24 @@ import mongoose, { Schema } from 'mongoose'; -import {QuoteDbModel, RegisterPayload} from '../models'; +import { PeginQuoteDbModel, PegoutQuoteDbModel, RegisterPayload } from '../models'; import {FlyoverStatuses, FlyoverStatusModel} from '../models/flyover-status.model'; import {MongoDbDataService} from './mongodb-data.service'; import { RskNodeService } from './rsk-node.service'; +import { stringWeiToDecimalString, stringSatoshiToDecimalString } from '../utils/parseUnits'; +import * as constants from '../constants'; interface FlyoverStatusMongoModel extends mongoose.Document, FlyoverStatusModel {} -const quoteSchema = new Schema({ - agreementTimestamp: {type: Number}, - gasFeeOnWei: {type: Schema.Types.BigInt}, - nonce: {type: Schema.Types.BigInt}, - penaltyFeeOnWei: {type: Schema.Types.BigInt}, - btcRefundAddress: {type: String}, - lbcAddress: {type: String}, - lpBtcAddress: {type: String}, - rskRefundAddress: {type: String}, - liquidityProviderRskAddress: {type: String}, - callFeeOnSatoshi: {type: Schema.Types.BigInt}, - callOnRegister: {type: Boolean}, - confirmations: {type: Number}, - contractAddr: {type: String}, - data: {type: String}, - fedBTCAddr: {type: String}, - gasLimit: {type: Schema.Types.BigInt}, - lpCallTime: {type: Number}, - productFeeAmountOnSatoshi: {type: Schema.Types.BigInt}, - timeForDepositInSeconds: {type: Number}, - valueOnSatoshi: {type: Schema.Types.BigInt}, -}) - const FlyoverStatusSchema = new mongoose.Schema({ txHash: {type: String, required: true}, date: {type: Date, required: true}, type: {type: String, required: true}, - amount: {type: Number, required: true}, - fee: {type: Number, required: true}, - blockToBeFinished: {type: Number, required: true}, + amount: {type: String, required: true}, + fee: {type: String, required: true}, + blockToBeFinished: {type: String, required: true}, senderAddress: {type: String, required: true}, recipientAddress: {type: String, required: true}, quoteHash: {type: String, required: true}, - quote: quoteSchema, + quote: {type: Schema.Types.Mixed, required: true}, acceptedQuoteSignature: {type: String}, }); @@ -85,41 +64,18 @@ export class FlyoverService extends MongoDbDataService { const currentBlock = await this.rskNodeService.getBlockNumber(); const flyoverStatus = new FlyoverStatusModel(); + const feePlusGas = (BigInt(payload?.fee ?? 0) + BigInt(payload?.rskGas ?? 0)); + if (payload.type === constants.TX_TYPE_PEGIN) { + flyoverStatus.amount = stringSatoshiToDecimalString(payload.value); + flyoverStatus.fee = stringSatoshiToDecimalString(feePlusGas.toString()); + flyoverStatus.quote = { + ...payload?.quote, + ...(payload?.quote?.callFeeOnSatoshi && { callFeeOnSatoshi: stringSatoshiToDecimalString(payload?.quote?.callFeeOnSatoshi) }), + ...(payload?.quote?.gasFeeOnWei && { gasFeeOnWei: stringWeiToDecimalString(payload?.quote?.gasFeeOnWei) }), + ...(payload?.quote?.gasLimit && { gasLimit: payload?.quote?.gasLimit }), + ...(payload?.quote?.penaltyFeeOnWei && { penaltyFeeOnWei: stringWeiToDecimalString(payload?.quote?.penaltyFeeOnWei) }), + ...(payload?.quote?.productFeeAmountOnSatoshi && { productFeeAmountOnSatoshi: stringSatoshiToDecimalString(payload?.quote?.productFeeAmountOnSatoshi) }), + ...(payload?.quote?.valueOnSatoshi && { valueOnSatoshi: stringSatoshiToDecimalString(payload?.quote?.valueOnSatoshi) }), + } as PeginQuoteDbModel; + } else { + flyoverStatus.amount = stringWeiToDecimalString(payload.value); + flyoverStatus.fee = stringWeiToDecimalString(feePlusGas.toString()); + flyoverStatus.quote = { + ...payload?.quote, + ...(payload?.quote?.callFeeOnWei && { callFeeOnWei: stringWeiToDecimalString(payload?.quote?.callFeeOnWei) }), + ...(payload?.quote?.gasFeeOnWei && { gasFeeOnWei: stringWeiToDecimalString(payload?.quote?.gasFeeOnWei) }), + ...(payload?.quote?.penaltyFeeOnWei && { penaltyFeeOnWei: stringWeiToDecimalString(payload?.quote?.penaltyFeeOnWei) }), + ...(payload?.quote?.productFeeAmountOnWei && { productFeeAmountOnWei: stringWeiToDecimalString(payload?.quote?.productFeeAmountOnWei) }), + ...(payload?.quote?.valueOnWei && { valueOnWei: stringWeiToDecimalString(payload?.quote?.valueOnWei) }), + } as PegoutQuoteDbModel; + } flyoverStatus.txHash = payload.txHash; flyoverStatus.date = new Date(); flyoverStatus.type = payload.type; - flyoverStatus.amount = payload.value; - flyoverStatus.fee = (payload?.fee ?? 0) + (payload?.rskGas ?? 0); flyoverStatus.senderAddress = payload?.details?.senderAddress ?? ''; flyoverStatus.recipientAddress = payload?.details?.recipientAddress ?? ''; flyoverStatus.blockToBeFinished = currentBlock + Number(payload?.details?.blocksToCompleteTransaction ?? 0); flyoverStatus.quoteHash = payload?.quoteHash ?? ''; - flyoverStatus.quote = { ...payload?.quote , ...(payload?.quote?.gasLimit && { gasLimit: BigInt(payload?.quote?.gasLimit) })} as QuoteDbModel; flyoverStatus.acceptedQuoteSignature = payload?.acceptedQuoteSignature ?? ''; return this.set(flyoverStatus); } diff --git a/src/services/register.service.ts b/src/services/register.service.ts index 39e89b77..7ed09c0c 100644 --- a/src/services/register.service.ts +++ b/src/services/register.service.ts @@ -2,6 +2,8 @@ import mongoose from 'mongoose'; import {RegisterCallPayload, RegisterPayload} from '../models'; import {AppTxModel} from '../models/app-tx.model'; import {MongoDbDataService} from './mongodb-data.service'; +import { stringSatoshiToDecimalString, stringWeiToDecimalString } from '../utils/parseUnits'; +import * as constants from '../constants'; interface AppTxMongoModel extends mongoose.Document, AppTxModel {} @@ -9,11 +11,11 @@ const AppTxSchema = new mongoose.Schema({ txHash: {type: String, required: true}, type: {type: String, required: true}, creationDate: {type: Date, required: true}, - value: {type: Number, required: true}, + value: {type: String, required: true}, wallet: {type: String, required: true}, - fee: {type: Number, required: true}, - rskGas: {type: Number, required: true}, - btcEstimatedFee: {type: Number, required: true}, + fee: {type: String, required: true}, + rskGas: {type: String, required: true}, + btcEstimatedFee: {type: String, required: true}, provider: {type: String, required: true}, }); @@ -49,12 +51,14 @@ export class RegisterService extends MongoDbDataService { + if(value === '0') return '0'; + return formatUnits(BigInt(value), 18); +}; +export const stringSatoshiToDecimalString = (value: string) => { + if(value === '0') return '0'; + return formatUnits(BigInt(value), 8); +}; \ No newline at end of file From 9b917f1d1909e56199dab0e15ac00fc7ea5fee14 Mon Sep 17 00:00:00 2001 From: ronaldsg Date: Mon, 24 Feb 2025 11:05:16 -0500 Subject: [PATCH 2/2] Include test for Resgister on flyover service --- .../services/flyover-service.service.unit.ts | 178 ++++++++++++++---- src/__tests__/unit/utils/parse-units.unit.ts | 4 - 2 files changed, 145 insertions(+), 37 deletions(-) diff --git a/src/__tests__/unit/services/flyover-service.service.unit.ts b/src/__tests__/unit/services/flyover-service.service.unit.ts index 739557b2..a06dff77 100644 --- a/src/__tests__/unit/services/flyover-service.service.unit.ts +++ b/src/__tests__/unit/services/flyover-service.service.unit.ts @@ -1,38 +1,150 @@ -// import { expect } from '@loopback/testlab'; -// import { FlyoverService } from '../../../services/flyover.service'; -// import { RegisterPayload } from '../../../models/register-payload.model'; -// import { FlyoverStatusModel } from '../../../models/flyover-status.model'; -// import { RskNodeService } from '../../../services/rsk-node.service'; -// import sinon from 'sinon'; +import { expect } from '@loopback/testlab'; +import { FlyoverService } from '../../../services/flyover.service'; +import { RegisterPayload } from '../../../models/register-payload.model'; +import { RskNodeService } from '../../../services/rsk-node.service'; +import sinon from 'sinon'; +import { MongoDbDataSource } from '../../../datasources/mongodb.datasource'; -// describe('Service: FlyoverService', () => { -// let flyoverService: FlyoverService; -// let rskNodeService: RskNodeService; +describe('Service: FlyoverService', () => { + let flyoverService: FlyoverService; + let rskNodeService: RskNodeService; -// beforeEach(() => { -// rskNodeService = new RskNodeService(); -// flyoverService = new FlyoverService(); -// }); + beforeEach(() => { + rskNodeService = new RskNodeService(); + const mongoDbDataSource = sinon.createStubInstance(MongoDbDataSource); + flyoverService = new FlyoverService(mongoDbDataSource); + }); -// afterEach(() => { -// sinon.restore(); -// }); -// describe('Service: FlyoverService', () => { -// it('should register a pegin native transaction successfully', async () => { -// const mockBlockNumber = 1000; -// sinon.stub(rskNodeService, 'getBlockNumber').resolves(mockBlockNumber); -// sinon.stub(flyoverService, 'set').resolves(true); + afterEach(() => { + sinon.restore(); + }); + describe('Register:', () => { + it('should register a pegin native transaction successfully', async () => { + const mockBlockNumber = 1000; + sinon.stub(rskNodeService, 'getBlockNumber').resolves(mockBlockNumber); + sinon.stub(flyoverService, 'set').resolves(true); -// const payload: RegisterPayload = { -// "txHash": "0x807f14318a2f4bc62ae3a14370c243087464740fb2f5b16763f2fb1635708bb4", -// "type": "pegout", -// "value": "8000000000000000", -// "wallet": "Metamask", -// "btcEstimatedFee": "745632", -// "rskGas": "234858360000" -// }; + const payload: RegisterPayload = new RegisterPayload( { + "txHash": "996de55f617c8aeb470cd8f0afd829de5169f8bedbc8bc8d45bb0ba656b0385e", + "type": "pegin", + "wallet": "leather", + "addressType": "Native segwit", + "value": "500000", + "fee": "1596" + }); -// const result = await flyoverService.register(payload); -// expect(result).to.be.true(); -// }); -// }); + const result = await flyoverService.register(payload); + expect(result).to.be.true(); + }); + it('should register a pegout native transaction successfully', async () => { + const mockBlockNumber = 1000; + sinon.stub(rskNodeService, 'getBlockNumber').resolves(mockBlockNumber); + sinon.stub(flyoverService, 'set').resolves(true); + + const payload: RegisterPayload = new RegisterPayload( { + "txHash": "0x807f14318a2f4bc62ae3a14370c243087464740fb2f5b16763f2fb1635708bb4", + "type": "pegout", + "value": "8000000000000000", + "wallet": "Metamask", + "btcEstimatedFee": "745632", + "rskGas": "234858360000" + }); + + const result = await flyoverService.register(payload); + expect(result).to.be.true(); + }); + it('should register a pegout flyover transaction successfully', async () => { + const mockBlockNumber = 1000; + sinon.stub(rskNodeService, 'getBlockNumber').resolves(mockBlockNumber); + sinon.stub(flyoverService, 'set').resolves(true); + + const payload: RegisterPayload = new RegisterPayload( { + "txHash": "0xebafb8b598395d07693e7de1e585fa518293a49b7598b5f33a525a62c09abe78", + "type": "pegout", + "value": "5000000000000000", + "wallet": "Metamask", + "rskGas": "79040000000000", + "fee": "100000000000000", + "provider": "RSK Provider", + "details": { + "senderAddress": "0x7509517a1880B14C9d734c55fAc18C7737EC11c5", + "recipientAddress": "tb1qndk5wmvg0k6p8mg2t8amr65qa4qkg8nstsnea7", + "blocksToCompleteTransaction": "10" + }, + "quote": { + "agreementTimestamp": "1740092905", + "btcRefundAddress": "tb1qndk5wmvg0k6p8mg2t8amr65qa4qkg8nstsnea7", + "callFeeOnWei": "100000000000000", + "depositAddr": "tb1qndk5wmvg0k6p8mg2t8amr65qa4qkg8nstsnea7", + "depositConfirmations": "10", + "depositDateLimit": "1740100105", + "expireBlocks": "6094589", + "expireDate": "1740093405", + "gasFeeOnWei": "79040000000000", + "lbcAddress": "0xc2A630c053D12D63d32b025082f6Ba268db18300", + "liquidityProviderRskAddress": "0x7c4890a0f1d4bbf2c669ac2d1effa185c505359b", + "lpBtcAddress": "mvL2bVzGUeC9oqVyQWJ4PxQspFzKgjzAqe", + "nonce": "8353044002070248232", + "penaltyFeeOnWei": "10000000000000", + "productFeeAmountOnWei": "0", + "rskRefundAddress": "0x7509517a1880B14C9d734c55fAc18C7737EC11c5", + "transferConfirmations": "2", + "transferTime": "7200", + "valueOnWei": "5000000000000000" + }, + "quoteHash": "70f5973bf6ac8d5ba00ec0f1204b4d372038a953ada2022540654d9a33511b41", + "acceptedQuoteSignature": "ba40a7fe2af7211d2fb788c5d9cbfced7caab5a932fdecc9910df450fc992b613a5118432edcf6045658f9289c0fac802d9ceba093274719d1a839897a49c67f1b" + }); + + const result = await flyoverService.register(payload); + expect(result).to.be.true(); + }); + it('should register a pegin flyover transaction successfully', async () => { + const mockBlockNumber = 1000; + sinon.stub(rskNodeService, 'getBlockNumber').resolves(mockBlockNumber); + sinon.stub(flyoverService, 'set').resolves(true); + + const payload: RegisterPayload = new RegisterPayload( { + "acceptedQuoteSignature": "bab6986b5eee4e9455079155d33908b3b81ae2d090deabf8f04fcc5ef911486a4c9a7a2545af1fccfbdf56777a25c0c6a045eaba92355123454881dc0ba1f32c1c", + "addressType": "Native segwit", + "details": { + "blocksToCompleteTransaction": "2", + "recipientAddress": "0x7509517a1880b14c9d734c55fac18c7737ec11c5", + "senderAddress": "tb1qndk5wmvg0k6p8mg2t8amr65qa4qkg8nstsnea7" + }, + "fee": "11028", + "provider": "teks-staging", + "quote": { + "agreementTimestamp": "1740086704", + "btcRefundAddress": "mfWxJ45yp2SFn7UciZyNpvDKrzbhyfKrY8", + "callFeeOnSatoshi": "10000", + "callOnRegister": false, + "confirmations": "2", + "contractAddr": "0x7509517a1880b14c9d734c55fac18c7737ec11c5", + "data": "0x", + "fedBTCAddr": "2N3GznpmcBbymsK53Q1eh4NCorKbYN9wKr2", + "gasFeeOnWei": "111872628000", + "gasLimit": "21000", + "lbcAddress": "0xc2A630c053D12D63d32b025082f6Ba268db18300", + "liquidityProviderRskAddress": "0x113ed582b39490cada59b7fc6cffe1dd4cba5e4b", + "lpBtcAddress": "mtkgpHyZzRspgkt3nUNV7xJRrwnMCPbuPW", + "lpCallTime": "14400", + "nonce": "1746424005804806700", + "penaltyFeeOnWei": "10000000000000", + "productFeeAmountOnSatoshi": "0", + "rskRefundAddress": "0x7509517a1880b14c9d734c55fac18c7737ec11c5", + "timeForDepositInSeconds": "10800", + "valueOnSatoshi": "500000" + }, + "quoteHash": "f49c2190c649100e26518937bf072eb172c5e938089f277ebbb2e355dcf00ddc", + "txHash": "da7cc5b956607830e70c13ab26225439f2f2a427715ed81d8ca714bdf381d7ce", + "type": "pegin", + "value": "500000", + "wallet": "leather" + }); + + const result = await flyoverService.register(payload); + expect(result).to.be.true(); + }); + }); +}); diff --git a/src/__tests__/unit/utils/parse-units.unit.ts b/src/__tests__/unit/utils/parse-units.unit.ts index b186cc55..cd2a19be 100644 --- a/src/__tests__/unit/utils/parse-units.unit.ts +++ b/src/__tests__/unit/utils/parse-units.unit.ts @@ -14,8 +14,4 @@ describe('ParseUnits', () => { const stringValueInSatoshis = "0"; expect(stringSatoshiToDecimalString(stringValueInSatoshis)).to.be.eql("0"); }); - it('should return zero string value of a wei string 0', () => { - const stringValueInWei = "79040000000000"; - expect(stringWeiToDecimalString(stringValueInWei)).to.be.eql("0"); - }); }); \ No newline at end of file