From de98527b257f01cdd6fdfb2feb8a0cacfb529bca Mon Sep 17 00:00:00 2001 From: Michal S Date: Fri, 20 Sep 2024 12:39:03 +0100 Subject: [PATCH] fix(wallet-mobile): Use absolute slot number when creating a TX (#3642) --- .../helpers/date-to-epoch-info.test.ts | 5 +++ .../helpers/date-to-epoch-info.ts | 1 + .../helpers/epoch-progress.test.ts | 6 ++++ .../network-manager/helpers/epoch-progress.ts | 29 ++++++++++++---- .../yoroi-wallets/cardano/cardano-wallet.ts | 34 +++++++------------ packages/types/src/network/manager.ts | 2 ++ 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts index 032bddaf2e..1d313b544e 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.test.ts @@ -18,6 +18,7 @@ describe('dateToEpochInfo', () => { start: new Date('2024-05-09T21:44:51.000Z'), end: new Date('2024-05-14T21:44:51.000Z'), era: shelleyEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -42,6 +43,7 @@ describe('dateToEpochInfo', () => { start: new Date('2017-09-23T21:44:51.000Z'), end: new Date('2017-09-28T21:44:51.000Z'), era: byronEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -58,6 +60,7 @@ describe('dateToEpochInfo', () => { start: new Date('2020-07-24T21:44:51.000Z'), end: new Date('2020-07-29T21:44:51.000Z'), era: byronEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -75,6 +78,7 @@ describe('dateToEpochInfo', () => { start: new Date('2020-07-29T21:44:51.000Z'), end: new Date('2020-08-03T21:44:51.000Z'), era: shelleyEraConfig, + eras: networkManagers[Chain.Network.Mainnet].eras, } const result = convertDateToEpoch(inputDate) @@ -91,6 +95,7 @@ describe('dateToEpochInfo', () => { start: new Date('2024-05-11T01:00:00.000Z'), end: new Date('2024-05-16T01:00:00.000Z'), era: shelleyPreprodEraConfig, + eras: networkManagers['preprod'].eras, } const result = convertDateToEpoch(inputDate) diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts index f7031a1102..d4d5fc77ee 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/date-to-epoch-info.ts @@ -17,6 +17,7 @@ export function dateToEpochInfo(eras: Network.Manager['eras']) { start: epochStart, end: epochEnd, era: era, + eras: eras, }) } diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts index 37b686c9e7..c5ace04ceb 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.test.ts @@ -15,6 +15,7 @@ describe('epochProgress', () => { expect(result).toEqual({ progress: 100, currentSlot: 431999, + absoluteSlot: 124156799, timeRemaining: {days: 0, hours: 0, minutes: 0, seconds: 1}, }) }) @@ -24,6 +25,7 @@ describe('epochProgress', () => { const result = epochProgress(dateToEpochInfo(networkManagers['mainnet'].eras)(currentDate))(currentDate) expect(result).toEqual({ + absoluteSlot: 123724800, progress: 0, currentSlot: 0, timeRemaining: {days: 5, hours: 0, minutes: 0, seconds: 0}, @@ -35,6 +37,7 @@ describe('epochProgress', () => { const result = epochProgress(dateToEpochInfo(networkManagers['mainnet'].eras)(currentDate))(currentDate) expect(result).toEqual({ + absoluteSlot: 123940800, progress: 50, currentSlot: 216000, timeRemaining: {days: 2, hours: 12, minutes: 0, seconds: 0}, @@ -47,6 +50,7 @@ describe('epochProgress', () => { start: new Date('2024-05-09T21:44:51.000Z'), end: new Date('2024-05-14T21:44:51.000Z'), era: shelleyEraConfig, + eras: networkManagers['mainnet'].eras, } const currentDate = new Date('2022-01-02T00:00:01Z') @@ -56,6 +60,7 @@ describe('epochProgress', () => { expect(result).toEqual({ progress: 100, currentSlot: 432000, + absoluteSlot: 49515310, timeRemaining: {days: 0, hours: 0, minutes: 0, seconds: 0}, }) }) @@ -68,6 +73,7 @@ describe('epochProgress', () => { const result = progressFn(currentDate) expect(result).toEqual({ + absoluteSlot: 61718400, progress: 86.67, currentSlot: 374400, timeRemaining: {days: 0, hours: 16, minutes: 0, seconds: 0}, diff --git a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts index d412bce685..a6ef809775 100644 --- a/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts +++ b/apps/wallet-mobile/src/features/WalletManager/network-manager/helpers/epoch-progress.ts @@ -6,11 +6,24 @@ export function epochProgress(epochInfo: Network.EpochInfo) { const epochStart = epochInfo.start const epochEnd = epochInfo.end - if (date > epochEnd || date < epochStart) + let absoluteSlot = 0 + + for (const era of epochInfo.eras) { + if (date >= era.start && (era.end === undefined || date < era.end)) { + absoluteSlot += Math.floor((date.getTime() - era.start.getTime()) / 1e3 / era.slotInSeconds) + break + } + absoluteSlot += Math.floor( + ((era.end?.getTime() ?? date.getTime()) - era.start.getTime()) / 1e3 / era.slotInSeconds, + ) + } + + if (date > epochEnd || date < epochStart) { return freeze( { progress: 100, currentSlot: epochInfo.era.slotsPerEpoch, + absoluteSlot, timeRemaining: { days: 0, hours: 0, @@ -20,6 +33,7 @@ export function epochProgress(epochInfo: Network.EpochInfo) { }, true, ) + } const progress = Math.round( @@ -36,13 +50,14 @@ export function epochProgress(epochInfo: Network.EpochInfo) { return freeze( { - progress: progress, - currentSlot: currentSlot, + progress, + currentSlot, + absoluteSlot, timeRemaining: { - days: days, - hours: hours, - minutes: minutes, - seconds: seconds, + days, + hours, + minutes, + seconds, }, }, true, diff --git a/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts b/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts index dae44280f1..52df12db52 100644 --- a/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts +++ b/apps/wallet-mobile/src/yoroi-wallets/cardano/cardano-wallet.ts @@ -371,12 +371,9 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio addressMode: Wallet.AddressMode }) { if (implementationConfig.features.staking) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() const registrationStatus = this.getDelegationStatus().isRegistered @@ -437,11 +434,7 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio const primaryTokenId = this.portfolioPrimaryTokenInfo.id try { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) - - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const votingPublicKey = await Promise.resolve(Buffer.from(catalystKeyHex, 'hex')) .then((bytes) => CardanoMobile.PrivateKey.fromExtendedBytes(bytes)) .then((key) => key.toPublic()) @@ -528,12 +521,9 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio addressMode: Wallet.AddressMode }): Promise { if (implementationConfig.features.staking) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() const accountState = await legacyApi.getAccountState( @@ -589,11 +579,8 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio votingCertificates: CardanoTypes.Certificate[] addressMode: Wallet.AddressMode }) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() @@ -758,6 +745,13 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio return Promise.resolve(addressedUtxos) } + private async getAbsoluteSlotNumber() { + const time = await this.checkServerStatus() + .then(({serverTime}) => serverTime || Date.now()) + .catch(() => Date.now()) + return new BigNumber(this.networkManager.epoch.progress(new Date(time)).absoluteSlot) + } + async createUnsignedTx({ entries, addressMode, @@ -767,11 +761,9 @@ export const makeCardanoWallet = (networkManager: Network.Manager, implementatio addressMode: Wallet.AddressMode metadata?: Array }) { - const time = await this.checkServerStatus() - .then(({serverTime}) => serverTime || Date.now()) - .catch(() => Date.now()) const primaryTokenId = this.portfolioPrimaryTokenInfo.id - const absSlotNumber = new BigNumber(this.networkManager.epoch.progress(new Date(time)).currentSlot) + const absSlotNumber = await this.getAbsoluteSlotNumber() + const changeAddr = this.getAddressedChangeAddress(addressMode) const addressedUtxos = await this.getAddressedUtxos() diff --git a/packages/types/src/network/manager.ts b/packages/types/src/network/manager.ts index fa1807fa04..705cec63c1 100644 --- a/packages/types/src/network/manager.ts +++ b/packages/types/src/network/manager.ts @@ -53,11 +53,13 @@ export type NetworkEpochInfo = { start: Date end: Date era: NetworkEraConfig + eras: ReadonlyArray } export type NetworkEpochProgress = { progress: number currentSlot: number + absoluteSlot: number timeRemaining: { days: number hours: number