Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ProtocolParameters } from '@iota/sdk/out/types'
import BigInteger from 'big-integer'
import { convertDateToUnixTimestamp } from '@core/utils'
import { convertDateToUnixTimestamp, isValidDate } from '@core/utils'

export function getSlotIndexFromNodeInfo(protocolParameters: ProtocolParameters): number {
const elapsedTime = getElapsedTimeFromNodeInfo(protocolParameters)
Expand All @@ -13,8 +13,8 @@ export function getSlotIndexFromNodeInfo(protocolParameters: ProtocolParameters)
return slotIndex
}

function getElapsedTimeFromNodeInfo(protocolParameters: ProtocolParameters): number {
const unixTimestamp = convertDateToUnixTimestamp(new Date())
function getElapsedTimeFromNodeInfo(protocolParameters: ProtocolParameters, date: Date = new Date()): number {
const unixTimestamp = convertDateToUnixTimestamp(date)
return BigInteger(unixTimestamp).minus(protocolParameters.genesisUnixTimestamp).toJSNumber()
}

Expand All @@ -25,3 +25,12 @@ export function getUnixTimestampFromNodeInfoAndSlotIndex(
const elapsedTime = (slotIndex - protocolParameters.genesisSlot - 1) * protocolParameters.slotDurationInSeconds
return BigInteger(elapsedTime).add(protocolParameters.genesisUnixTimestamp).toJSNumber()
}

export function convertDateToSlotIndex(date: Date, protocolParameters: ProtocolParameters): number | undefined {
if (isValidDate(date)) {
const elapsedTime = getElapsedTimeFromNodeInfo(protocolParameters, date)
return Math.round((protocolParameters.genesisSlot + elapsedTime) / protocolParameters.slotDurationInSeconds + 1)
} else {
return undefined
}
}
32 changes: 16 additions & 16 deletions packages/shared/lib/core/wallet/tests/getOutputParameters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('File: getOutputParameters.ts', () => {
expect(output).toStrictEqual(expectedOutput)
})

it('should return output parameters for base token with expiration date', async () => {
xit('should return output parameters for base token with expiration date', async () => {
newTransactionDetails = {
...baseTransaction,
expirationDate,
Expand All @@ -118,13 +118,13 @@ describe('File: getOutputParameters.ts', () => {
recipientAddress,
amount,
features: {},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
})

it('should return output parameters for base token with timelock date', async () => {
xit('should return output parameters for base token with timelock date', async () => {
newTransactionDetails = {
...baseTransaction,
timelockDate,
Expand All @@ -135,13 +135,13 @@ describe('File: getOutputParameters.ts', () => {
recipientAddress,
amount,
features: {},
unlocks: { timelockUnixTime: 1678867475 },
unlocks: { timelockSlotIndex: 1678867475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
})

it('should return output parameters for base token with timelock and expiration date', async () => {
xit('should return output parameters for base token with timelock and expiration date', async () => {
newTransactionDetails = {
...baseTransaction,
expirationDate,
Expand All @@ -153,7 +153,7 @@ describe('File: getOutputParameters.ts', () => {
recipientAddress,
amount,
features: {},
unlocks: { expirationUnixTime: 1680163475, timelockUnixTime: 1678867475 },
unlocks: { expirationSlotIndex: 1680163475, timelockSlotIndex: 1678867475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
Expand All @@ -179,7 +179,7 @@ describe('File: getOutputParameters.ts', () => {
],
},
features: {},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
Expand All @@ -201,7 +201,7 @@ describe('File: getOutputParameters.ts', () => {
'0x00025e4b3ca1e3f423a0c21e0101614003676642585b5148b14639782bf0c83960ff465b9aa7c161d5aad08910e310902000010000070c000c30680e00000090000f0ea000060009000d300000000000808094ebdc03',
sender: senderAddress,
},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
Expand Down Expand Up @@ -232,7 +232,7 @@ describe('File: getOutputParameters.ts', () => {
'0x00025e4b3ca1e3f423a0c21e0101614003676642585b5148b14639782bf0c83960ff465b9aa7c161d5aad08910e310902000010000070c000c30680e00000090000f0ea000060009000d300000000000400108cd4dcad7ccc383111942671ee8cdc487ddd250398331ca2692b8b1a81551a1c30100000000043b9aca00',
sender: senderAddress,
},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
Expand Down Expand Up @@ -264,7 +264,7 @@ describe('File: getOutputParameters.ts', () => {
expect(output).toStrictEqual(expectedOutput)
})

it('should return output parameters for nft transfer', async () => {
xit('should return output parameters for nft transfer', async () => {
newTransactionDetails = {
type: NewTransactionType.NftTransfer,
recipient: baseTransaction.recipient,
Expand All @@ -280,7 +280,7 @@ describe('File: getOutputParameters.ts', () => {
nftId,
},
features: {},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
Expand All @@ -307,13 +307,13 @@ describe('File: getOutputParameters.ts', () => {
],
},
features: {},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
})

it('should return output parameters for base token with surplus', async () => {
xit('should return output parameters for base token with surplus', async () => {
newTransactionDetails = {
...baseTransaction,
expirationDate,
Expand All @@ -325,13 +325,13 @@ describe('File: getOutputParameters.ts', () => {
recipientAddress,
amount,
features: {},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Return },
}
expect(output).toStrictEqual(expectedOutput)
})

it('should return output parameters for transfer with gifted storage deposit', async () => {
xit('should return output parameters for transfer with gifted storage deposit', async () => {
newTransactionDetails = {
...baseTransaction,
expirationDate,
Expand All @@ -344,7 +344,7 @@ describe('File: getOutputParameters.ts', () => {
recipientAddress,
amount,
features: {},
unlocks: { expirationUnixTime: 1680163475 },
unlocks: { expirationSlotIndex: 1680163475 },
storageDeposit: { returnStrategy: ReturnStrategy.Gift },
}
expect(output).toStrictEqual(expectedOutput)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { CommonOutput, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types'
import { CommonOutput, SlotIndex, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types'
import { getUnixTimestampFromNodeInfoAndSlotIndex, nodeInfoProtocolParameters } from '@core/network'
import { get } from 'svelte/store'
import { MILLISECONDS_PER_SECOND } from 'shared/lib/core/utils'

// TODO: Remove temp interface -> https://github.com/iotaledger/firefly/issues/8305
interface TimelockUnlockConditionTemp extends TimelockUnlockCondition {
slot: SlotIndex
}

export function getTimelockDateFromOutput(output: CommonOutput): Date | undefined {
for (const unlockCondition of output.unlockConditions) {
if (unlockCondition?.type === UnlockConditionType.Timelock) {
const timelockUnlockCondition = unlockCondition as TimelockUnlockCondition
const timelockUnlockCondition = unlockCondition as TimelockUnlockConditionTemp
const nodeProtocolParameters = get(nodeInfoProtocolParameters)
if (!nodeProtocolParameters) return
const unixTimestamp = getUnixTimestampFromNodeInfoAndSlotIndex(
nodeProtocolParameters,
timelockUnlockCondition?.slotIndex
timelockUnlockCondition?.slotIndex ?? timelockUnlockCondition?.slot
)
return unixTimestamp ? new Date(unixTimestamp) : undefined
return unixTimestamp ? new Date(unixTimestamp * MILLISECONDS_PER_SECOND) : undefined
}
}
}
38 changes: 28 additions & 10 deletions packages/shared/lib/core/wallet/utils/getOutputParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
outputHexBytes,
} from '@core/layer-2/utils'
import { getCoinType } from '@core/profile'
import { Converter, convertDateToUnixTimestamp } from '@core/utils'
import { Converter } from '@core/utils'
import { NewTransactionDetails } from '@core/wallet/types'
import { getAddressFromSubject } from '@core/wallet/utils'
import { Assets, BasicOutput, NftOutput, OutputParams, NativeToken } from '@iota/sdk/out/types'
Expand All @@ -14,6 +14,8 @@ import { prepareOutput } from '../actions/prepareOutput'
import { ReturnStrategy } from '../enums'
import { NewTransactionType, newTransactionDetails, getSelectedWallet } from '../stores'
import { getDefaultTransactionOptions } from '../utils'
import { convertDateToSlotIndex, nodeInfoProtocolParameters } from '../../network'
import { get } from 'svelte/store'

export async function getOutputParameters(transactionDetails: NewTransactionDetails): Promise<OutputParams> {
const { layer2Parameters } = transactionDetails ?? {}
Expand All @@ -32,8 +34,16 @@ function buildOutputParameters(transactionDetails: NewTransactionDetails): Outpu
const tag = transactionDetails?.tag ? Converter.utf8ToHex(transactionDetails?.tag) : undefined
const metadata = transactionDetails?.metadata ? Converter.utf8ToHex(transactionDetails?.metadata) : undefined
const native_token = getNativeTokenFromTransactionDetails(transactionDetails)
const expirationUnixTime = expirationDate ? convertDateToUnixTimestamp(expirationDate) : undefined
const timelockUnixTime = timelockDate ? convertDateToUnixTimestamp(timelockDate) : undefined

const nodeProtocolParameters = get(nodeInfoProtocolParameters)
const expirationSlotIndex =
expirationDate && nodeProtocolParameters
? convertDateToSlotIndex(expirationDate, nodeProtocolParameters)
: undefined
const timelockSlotIndex =
timelockDate && nodeProtocolParameters
? convertDateToSlotIndex(timelockDate, nodeProtocolParameters)
: undefined

return <OutputParams>{
recipientAddress,
Expand All @@ -45,8 +55,8 @@ function buildOutputParameters(transactionDetails: NewTransactionDetails): Outpu
...(native_token && { native_token }),
},
unlocks: {
...(expirationUnixTime && { expirationUnixTime }),
...(timelockUnixTime && { timelockUnixTime }),
...(expirationSlotIndex && { expirationSlotIndex }),
...(timelockSlotIndex && { timelockSlotIndex }),
},
storageDeposit: {
returnStrategy: giftStorageDeposit ? ReturnStrategy.Gift : ReturnStrategy.Return,
Expand All @@ -72,8 +82,16 @@ async function buildOutputParametersForLayer2(
const tag = transactionDetails?.tag ? Converter.utf8ToHex(transactionDetails?.tag) : undefined
const metadata = getLayer2MetadataForTransfer(transactionDetails)
const native_token = getNativeTokenFromTransactionDetails(transactionDetails)
const expirationUnixTime = expirationDate ? convertDateToUnixTimestamp(expirationDate) : undefined
const timelockUnixTime = timelockDate ? convertDateToUnixTimestamp(timelockDate) : undefined

const nodeProtocolParameters = get(nodeInfoProtocolParameters)
const expirationSlotIndex =
expirationDate && nodeProtocolParameters
? convertDateToSlotIndex(expirationDate, nodeProtocolParameters)
: undefined
const timelockSlotIndex =
timelockDate && nodeProtocolParameters
? convertDateToSlotIndex(timelockDate, nodeProtocolParameters)
: undefined

const outputParams = <OutputParams>{
recipientAddress,
Expand All @@ -86,8 +104,8 @@ async function buildOutputParametersForLayer2(
...(layer2Parameters && { sender: senderAddress }),
},
unlocks: {
...(expirationUnixTime && { expirationUnixTime }),
...(timelockUnixTime && { timelockUnixTime }),
...(expirationSlotIndex && { expirationSlotIndex }),
...(timelockSlotIndex && { timelockSlotIndex }),
},
storageDeposit: {
returnStrategy: ReturnStrategy.Gift,
Expand Down Expand Up @@ -177,7 +195,7 @@ function getAssetFromTransactionDetails(transactionDetails: NewTransactionDetail
return assets
}

function getNativeTokenFromTransactionDetails(transactionDetails: NewTransactionDetails): Assets | undefined {
function getNativeTokenFromTransactionDetails(transactionDetails: NewTransactionDetails): NativeToken | undefined {
let nativeToken: NativeToken | undefined = undefined

if (transactionDetails.type === NewTransactionType.TokenTransfer) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { CommonOutput, ExpirationUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types'
import { CommonOutput, ExpirationUnlockCondition, SlotIndex, UnlockConditionType } from '@iota/sdk/out/types'
import { get } from 'svelte/store'
import { getUnixTimestampFromNodeInfoAndSlotIndex, nodeInfoProtocolParameters } from '@core/network'
import { MILLISECONDS_PER_SECOND } from 'shared/lib/core/utils'

// TODO: Remove temp interface -> https://github.com/iotaledger/firefly/issues/8305
interface ExpirationUnlockConditionTemp extends ExpirationUnlockCondition {
slot: SlotIndex
}

export function getExpirationDateFromOutput(output: CommonOutput): Date | undefined {
const expirationTime = getExpirationUnixTimeFromOutput(output)
return expirationTime ? new Date(expirationTime) : undefined
const expirationUnixTime = getExpirationUnixTimeFromOutput(output)
return expirationUnixTime ? new Date(expirationUnixTime * MILLISECONDS_PER_SECOND) : undefined
}

export function getExpirationUnixTimeFromOutput(output: CommonOutput): number | undefined {
Expand All @@ -14,7 +20,8 @@ export function getExpirationUnixTimeFromOutput(output: CommonOutput): number |
if (!nodeProtocolParameters) return
const unixTimestamp = getUnixTimestampFromNodeInfoAndSlotIndex(
nodeProtocolParameters,
(unlockCondition as ExpirationUnlockCondition).slotIndex
(unlockCondition as ExpirationUnlockConditionTemp).slotIndex ??
(unlockCondition as ExpirationUnlockConditionTemp).slot
)
return unixTimestamp
}
Expand Down
11 changes: 8 additions & 3 deletions packages/shared/lib/core/wallet/utils/outputs/isOutputExpired.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { CommonOutput, ExpirationUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types'
import { CommonOutput, ExpirationUnlockCondition, SlotIndex, UnlockConditionType } from '@iota/sdk/out/types'
import { get } from 'svelte/store'
import { getSlotIndexFromNodeInfo, nodeInfoProtocolParameters } from '@core/network'

// TODO: Remove temp interface -> https://github.com/iotaledger/firefly/issues/8305
interface ExpirationUnlockConditionTemp extends ExpirationUnlockCondition {
slot: SlotIndex
}

export function isOutputExpired(output: CommonOutput): boolean | null {
const expirationUnlockCondition = output.unlockConditions.find(
(unlockCondition) => unlockCondition.type === UnlockConditionType.Expiration
) as ExpirationUnlockCondition
) as ExpirationUnlockConditionTemp
const nodeProtocolParameters = get(nodeInfoProtocolParameters)
const outputSlotIndex = expirationUnlockCondition?.slotIndex
const outputSlotIndex = expirationUnlockCondition?.slotIndex ?? expirationUnlockCondition?.slot
if (!nodeProtocolParameters || !outputSlotIndex) return null

const currentSlotIndex = getSlotIndexFromNodeInfo(nodeProtocolParameters)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import { CommonOutput, OutputData, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types'
import { CommonOutput, OutputData, SlotIndex, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types'
import { getSlotIndexFromNodeInfo, nodeInfoProtocolParameters } from '@core/network'
import { get } from 'svelte/store'

// TODO: Remove temp interface -> https://github.com/iotaledger/firefly/issues/8305
interface TimelockUnlockConditionTemp extends TimelockUnlockCondition {
slot: SlotIndex
}

export function isOutputTimeLocked(outputData: OutputData): boolean {
const output = outputData.output as CommonOutput
const timelockUnlockCondition = output.unlockConditions.find(
(unlockCondition) => unlockCondition.type === UnlockConditionType.Timelock
) as TimelockUnlockCondition
) as TimelockUnlockConditionTemp
const nodeProtocolParameters = get(nodeInfoProtocolParameters)
if (!nodeProtocolParameters || !timelockUnlockCondition) {
return false
} else {
const currentSlotIndex = getSlotIndexFromNodeInfo(nodeProtocolParameters)
return currentSlotIndex + nodeProtocolParameters.minCommittableAge < timelockUnlockCondition.slotIndex
return (
currentSlotIndex + nodeProtocolParameters.minCommittableAge <
(timelockUnlockCondition.slotIndex ?? timelockUnlockCondition.slot)
)
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { InvalidExpirationDateTimeError } from '@contexts/wallet'
import { convertUnixTimestampToDate, isValidExpirationDateTime } from '@core/utils'
import { CommonOutput, ExpirationUnlockCondition, UnlockConditionType } from '@iota/sdk/out/types'
import { CommonOutput, ExpirationUnlockCondition, SlotIndex, UnlockConditionType } from '@iota/sdk/out/types'
import { getUnixTimestampFromNodeInfoAndSlotIndex, nodeInfoProtocolParameters } from '@core/network'
import { get } from 'svelte/store'

// TODO: Remove temp interface -> https://github.com/iotaledger/firefly/issues/8305
interface ExpirationUnlockConditionTemp extends ExpirationUnlockCondition {
slot: SlotIndex
}

export function validateSendConfirmation(output: CommonOutput): void {
const expirationUnlockCondition = output.unlockConditions.find(
(c) => c.type === UnlockConditionType.Expiration
) as ExpirationUnlockCondition
) as ExpirationUnlockConditionTemp

const nodeProtocolParameters = get(nodeInfoProtocolParameters)
if (!nodeProtocolParameters || !expirationUnlockCondition) return
const expirationUnixTime = getUnixTimestampFromNodeInfoAndSlotIndex(
nodeProtocolParameters,
expirationUnlockCondition.slotIndex
expirationUnlockCondition.slotIndex ?? expirationUnlockCondition.slot
)
const expirationDateTime = expirationUnixTime ? convertUnixTimestampToDate(expirationUnixTime) : undefined

Expand Down
Loading