+
+
+
+ {#if !hideTokenInfo}
{token.metadata.name
? truncateString(token.metadata.name, 13, 0)
: truncateString(token.id, 6, 7)}
-
-
- {marketPrice ? formatCurrency(marketPrice) : ''}
-
-
-
-
- {/if}
-
-
-
- {token.metadata ? formatTokenAmountBestMatch(amount, token.metadata) : '-'}
-
-
-
- {marketBalance !== undefined ? `≈ ${formatCurrency(marketBalance)}` : ''}
+ {/if}
+
+ {token.metadata ? formatTokenAmountBestMatch(amount, token.metadata) : '-'}
+
+
+
+ {#if !hideTokenInfo}
+
+ {marketPrice ? formatCurrency(marketPrice) : ''}
+
+ {/if}
+
+ {marketBalance !== undefined ? `≈ ${formatCurrency(marketBalance)}` : '-'}
diff --git a/packages/shared/src/lib/auxiliary/deep-link/enums/send-operation-parameter.enum.ts b/packages/shared/src/lib/auxiliary/deep-link/enums/send-operation-parameter.enum.ts
index ab7350ff10..3e4989ad84 100644
--- a/packages/shared/src/lib/auxiliary/deep-link/enums/send-operation-parameter.enum.ts
+++ b/packages/shared/src/lib/auxiliary/deep-link/enums/send-operation-parameter.enum.ts
@@ -3,13 +3,18 @@
*/
export enum SendOperationParameter {
Address = 'address',
+ BaseCoinAmount = 'baseCoinAmount',
TokenId = 'tokenId',
- Amount = 'amount',
- Unit = 'unit',
+ TokenAmount = 'tokenAmount',
Metadata = 'metadata',
Tag = 'tag',
GiftStorageDeposit = 'giftStorageDeposit',
- Surplus = 'surplus',
DisableToggleGift = 'disableToggleGift',
DisableChangeExpiration = 'disableChangeExpiration',
+ DisableChangeTimelock = 'disableChangeTimelock',
+
+ // Firefly Specific
+ Surplus = 'surplus',
+ Amount = 'amount',
+ Unit = 'unit',
}
diff --git a/packages/shared/src/lib/auxiliary/deep-link/errors/amount-not-an-integer.error.ts b/packages/shared/src/lib/auxiliary/deep-link/errors/amount-not-an-integer.error.ts
index 9197433410..8ff84f959a 100644
--- a/packages/shared/src/lib/auxiliary/deep-link/errors/amount-not-an-integer.error.ts
+++ b/packages/shared/src/lib/auxiliary/deep-link/errors/amount-not-an-integer.error.ts
@@ -2,7 +2,7 @@ import { BaseError } from '@core/error'
import { localize } from '@core/i18n'
export class AmountNotAnIntegerError extends BaseError {
- constructor(amount: string) {
+ constructor(amount: string | null) {
const message = localize('notifications.deepLinkingRequest.invalidAmount', { values: { amount } })
super({
message,
diff --git a/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendConfirmationOperation.ts b/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendConfirmationOperation.ts
index 1554680fa8..dd3d17ec58 100644
--- a/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendConfirmationOperation.ts
+++ b/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendConfirmationOperation.ts
@@ -1,6 +1,6 @@
import { getActiveNetworkId } from '@core/network/actions'
import { getNetworkHrp } from '@core/profile/actions'
-import { getUnitFromTokenMetadata, validateTokenId } from '@core/token'
+import { validateTokenId } from '@core/token'
import { getTokenFromSelectedAccountTokens, selectedAccountTokens } from '@core/token/stores'
import { getByteLengthOfString, isStringTrue, validateBech32Address } from '@core/utils'
import {
@@ -20,13 +20,7 @@ import {
sendFlowRouter,
} from '../../../../../../../../desktop/views/dashboard/send-flow/send-flow.router'
import { SendOperationParameter } from '../../../enums'
-import {
- InvalidAddressError,
- NoAddressSpecifiedError,
- SurplusNotANumberError,
- SurplusNotSupportedError,
- UnknownAssetError,
-} from '../../../errors'
+import { InvalidAddressError, NoAddressSpecifiedError, UnknownAssetError } from '../../../errors'
import { getRawAmountFromSearchParam } from '../../../utils'
export function handleDeepLinkSendConfirmationOperation(searchParams: URLSearchParams): void {
@@ -56,49 +50,43 @@ export function handleDeepLinkSendConfirmationOperation(searchParams: URLSearchP
*/
function parseSendConfirmationOperation(searchParams: URLSearchParams): SendFlowParameters {
const networkId = getActiveNetworkId()
+ const baseCoin = get(selectedAccountTokens)?.[networkId]?.baseCoin
+ if (!baseCoin) {
+ throw new Error('No base coin')
+ }
+
+ let baseCoinTransfer: TokenTransferData | undefined
+ const baseCoinAmount = getRawAmountFromSearchParam(searchParams, SendOperationParameter.BaseCoinAmount)
+ if (baseCoinAmount) {
+ baseCoinTransfer = {
+ token: baseCoin,
+ rawAmount: baseCoinAmount,
+ }
+ }
const tokenId = searchParams.get(SendOperationParameter.TokenId)
if (tokenId) {
validateTokenId(tokenId)
}
- const type = tokenId ? SendFlowType.TokenTransfer : SendFlowType.BaseCoinTransfer
-
- const surplus = searchParams.get(SendOperationParameter.Surplus)
- if (surplus && parseInt(surplus).toString() !== surplus) {
- throw new SurplusNotANumberError(surplus)
- } else if (surplus && type === SendFlowType.TokenTransfer) {
- throw new SurplusNotSupportedError()
- }
-
- let baseCoinTransfer: TokenTransferData | undefined
let tokenTransfer: TokenTransferData | undefined
- if (type === SendFlowType.BaseCoinTransfer) {
- baseCoinTransfer = {
- token: get(selectedAccountTokens)?.[networkId]?.baseCoin,
- rawAmount: getRawAmountFromSearchParam(searchParams),
- unit: searchParams.get(SendOperationParameter.Unit) ?? 'glow',
- }
- } else if (type === SendFlowType.TokenTransfer && tokenId) {
+ const tokenAmount = getRawAmountFromSearchParam(searchParams, SendOperationParameter.TokenAmount)
+ if (tokenId && tokenAmount) {
const token = getTokenFromSelectedAccountTokens(tokenId, networkId)
if (token?.metadata) {
tokenTransfer = {
token,
- rawAmount: getRawAmountFromSearchParam(searchParams),
- unit: searchParams.get(SendOperationParameter.Unit) ?? getUnitFromTokenMetadata(token.metadata),
- }
- if (surplus) {
- baseCoinTransfer = {
- token: get(selectedAccountTokens)?.[networkId]?.baseCoin,
- rawAmount: surplus,
- unit: 'glow',
- }
+ rawAmount: tokenAmount,
}
} else {
throw new UnknownAssetError()
}
}
+ if (!baseCoinTransfer && !tokenTransfer) {
+ throw new Error('No transfer')
+ }
+
// Check address exists and is valid this is not optional.
const address = searchParams.get(SendOperationParameter.Address)
if (!address) {
@@ -124,9 +112,11 @@ function parseSendConfirmationOperation(searchParams: URLSearchParams): SendFlow
const giftStorageDeposit = isStringTrue(searchParams.get(SendOperationParameter.GiftStorageDeposit) ?? '')
const disableToggleGift = isStringTrue(searchParams.get(SendOperationParameter.DisableToggleGift) ?? '')
const disableChangeExpiration = isStringTrue(searchParams.get(SendOperationParameter.DisableChangeExpiration) ?? '')
+ const disableChangeTimelock = isStringTrue(searchParams.get(SendOperationParameter.DisableChangeTimelock) ?? '')
return {
- type,
+ type: tokenTransfer ? SendFlowType.TokenTransfer : SendFlowType.BaseCoinTransfer,
+ destinationNetworkId: networkId,
...(baseCoinTransfer && { baseCoinTransfer }),
...(tokenTransfer && { tokenTransfer }),
...(address && { recipient: { type: SubjectType.Address, address } }),
@@ -135,5 +125,6 @@ function parseSendConfirmationOperation(searchParams: URLSearchParams): SendFlow
...(giftStorageDeposit && { giftStorageDeposit }),
...(disableToggleGift && { disableToggleGift }),
...(disableChangeExpiration && { disableChangeExpiration }),
+ ...(disableChangeTimelock && { disableChangeTimelock }),
}
}
diff --git a/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendFormOperation.ts b/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendFormOperation.ts
index d7987c0087..a037879905 100644
--- a/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendFormOperation.ts
+++ b/packages/shared/src/lib/auxiliary/deep-link/handlers/wallet/operations/handleDeepLinkSendFormOperation.ts
@@ -46,13 +46,17 @@ function parseSendFormOperation(searchParams: URLSearchParams): SendFlowParamete
const tokenId = searchParams.get(SendOperationParameter.TokenId)
const type = tokenId ? SendFlowType.TokenTransfer : SendFlowType.BaseCoinTransfer
+ const baseCoin = get(selectedAccountTokens)?.[networkId]?.baseCoin
+ if (!baseCoin) {
+ throw new Error('No base coin')
+ }
let baseCoinTransfer: TokenTransferData | undefined
let tokenTransfer: TokenTransferData | undefined
if (type === SendFlowType.BaseCoinTransfer) {
baseCoinTransfer = {
- token: get(selectedAccountTokens)?.[networkId]?.baseCoin,
- rawAmount: getRawAmountFromSearchParam(searchParams),
+ token: baseCoin,
+ rawAmount: getRawAmountFromSearchParam(searchParams, SendOperationParameter.BaseCoinAmount),
unit: searchParams.get(SendOperationParameter.Unit) ?? 'glow',
}
} else if (type === SendFlowType.TokenTransfer && tokenId) {
@@ -60,7 +64,7 @@ function parseSendFormOperation(searchParams: URLSearchParams): SendFlowParamete
if (token?.metadata) {
tokenTransfer = {
token,
- rawAmount: getRawAmountFromSearchParam(searchParams),
+ rawAmount: getRawAmountFromSearchParam(searchParams, SendOperationParameter.TokenAmount),
unit: searchParams.get(SendOperationParameter.Unit) ?? getUnitFromTokenMetadata(token.metadata),
}
} else {
diff --git a/packages/shared/src/lib/auxiliary/deep-link/utils/getRawAmountFromSearchParam.ts b/packages/shared/src/lib/auxiliary/deep-link/utils/getRawAmountFromSearchParam.ts
index fe03099841..8bb83d30c3 100644
--- a/packages/shared/src/lib/auxiliary/deep-link/utils/getRawAmountFromSearchParam.ts
+++ b/packages/shared/src/lib/auxiliary/deep-link/utils/getRawAmountFromSearchParam.ts
@@ -1,7 +1,10 @@
import { AmountNotAnIntegerError, SendOperationParameter } from '@auxiliary/deep-link'
-export function getRawAmountFromSearchParam(searchParams: URLSearchParams): string {
- let rawAmount = searchParams.get(SendOperationParameter.Amount)
+export function getRawAmountFromSearchParam(
+ searchParams: URLSearchParams,
+ parameterKey: SendOperationParameter
+): string {
+ let rawAmount = searchParams.get(parameterKey)
const amount = Number(rawAmount)
if (!Number.isInteger(amount)) {
throw new AmountNotAnIntegerError(rawAmount)
diff --git a/packages/shared/src/lib/core/activity/utils/generateActivitiesFromBasicOutputs.ts b/packages/shared/src/lib/core/activity/utils/generateActivitiesFromBasicOutputs.ts
index 31670dbfe8..52e0f68101 100644
--- a/packages/shared/src/lib/core/activity/utils/generateActivitiesFromBasicOutputs.ts
+++ b/packages/shared/src/lib/core/activity/utils/generateActivitiesFromBasicOutputs.ts
@@ -47,7 +47,7 @@ export async function generateActivitiesFromBasicOutputs(
},
getNftId(nftInput.nftId, wrappedInput.outputId)
)
- const nft = buildNftFromNftOutput(wrappedInput, account.depositAddress, false)
+ const nft = buildNftFromNftOutput(wrappedInput, networkId, account.depositAddress, false)
addOrUpdateNftInAllAccountNfts(account.index, nft)
burnedNftInputs.splice(burnedNftInputIndex, 1)
diff --git a/packages/shared/src/lib/core/activity/utils/generateBaseActivity.ts b/packages/shared/src/lib/core/activity/utils/generateBaseActivity.ts
index 06913f4839..cc200b56b9 100644
--- a/packages/shared/src/lib/core/activity/utils/generateBaseActivity.ts
+++ b/packages/shared/src/lib/core/activity/utils/generateBaseActivity.ts
@@ -66,7 +66,7 @@ export async function generateBaseActivity(
persistedToken && nativeToken
? {
tokenId: persistedToken.id,
- rawAmount: String(nativeToken.amount),
+ rawAmount: String(Number(nativeToken.amount)),
}
: undefined
diff --git a/packages/shared/src/lib/core/activity/utils/helper/getMetadataFromOutput.ts b/packages/shared/src/lib/core/activity/utils/helper/getMetadataFromOutput.ts
index d607357844..92627ee5bc 100644
--- a/packages/shared/src/lib/core/activity/utils/helper/getMetadataFromOutput.ts
+++ b/packages/shared/src/lib/core/activity/utils/helper/getMetadataFromOutput.ts
@@ -12,9 +12,9 @@ export function getMetadataFromOutput(output: Output): string | undefined {
if (data) {
const isVotingOutput = isParticipationOutput(output)
const metadataBytes = Converter.hexToBytes(data)
- const startValue = Number(data.substring(0, 10))
+ const startValue = Number(data.substring(0, 4))
- // For smart contract calls the first 32 bits of the metadata
+ // For smart contract calls the first 8 bits of the metadata
// correspond to 0 if an an end-user initiates the transaction
// instead of a smart contract. A stop voting output could
// also start with a 0 metadata, so we check that as well.
diff --git a/packages/shared/src/lib/core/layer-2/actions/fetchSelectedAccountLayer2Balance.ts b/packages/shared/src/lib/core/layer-2/actions/fetchLayer2BalanceForAccount.ts
similarity index 67%
rename from packages/shared/src/lib/core/layer-2/actions/fetchSelectedAccountLayer2Balance.ts
rename to packages/shared/src/lib/core/layer-2/actions/fetchLayer2BalanceForAccount.ts
index a9ba9068ab..656eb9b83f 100644
--- a/packages/shared/src/lib/core/layer-2/actions/fetchSelectedAccountLayer2Balance.ts
+++ b/packages/shared/src/lib/core/layer-2/actions/fetchLayer2BalanceForAccount.ts
@@ -9,8 +9,16 @@ import { Converter } from '@core/utils/convert'
import { ISC_MAGIC_CONTRACT_ADDRESS } from '../constants'
import { evmAddressToAgentId, getAgentBalanceParameters, getSmartContractHexName } from '../helpers'
import { setLayer2AccountBalanceForChain } from '../stores'
+import { getNftsFromNftIds } from '@core/nfts/utils'
+import {
+ addNftsToDownloadQueue,
+ addOrUpdateNftInAllAccountNfts,
+ setNftInAllAccountNftsToUnspendable,
+} from '@core/nfts/actions'
+import { selectedAccountNfts } from '@core/nfts/stores'
+import { get } from 'svelte/store'
-export function fetchSelectedAccountLayer2Balance(account: IAccountState): void {
+export function fetchLayer2BalanceForAccount(account: IAccountState): void {
const { evmAddresses, index } = account
const chains = getNetwork()?.getChains() ?? []
chains.forEach(async (chain) => {
@@ -20,6 +28,8 @@ export function fetchSelectedAccountLayer2Balance(account: IAccountState): void
return
}
+ await fetchLayer2Nfts(evmAddress, chain, account.index)
+
const balances = await getLayer2BalanceForAddress(evmAddress, chain)
if (!balances) {
return
@@ -98,3 +108,35 @@ async function getLayer2Erc20BalancesForAddress(
}
return erc20TokenBalances
}
+
+async function fetchLayer2Nfts(evmAddress: string, chain: IChain, accountIndex: number): Promise
{
+ const accountsCoreContract = getSmartContractHexName('accounts')
+ const getBalanceFunc = getSmartContractHexName('accountNFTs')
+ const agentID = evmAddressToAgentId(evmAddress, chain.getConfiguration())
+ const parameters = getAgentBalanceParameters(agentID)
+ try {
+ const contract = chain.getContract(ContractType.IscMagic, ISC_MAGIC_CONTRACT_ADDRESS)
+ const nftResult = (await contract.methods
+ .callView(accountsCoreContract, getBalanceFunc, parameters)
+ .call()) as { items: { key: string; value: string }[] }
+
+ // the element with `key: "0x69"` just represents the length of the list, so it needs to be excluded
+ const nftIds = nftResult.items.filter((item) => item.key !== '0x69').map((item) => item.value)
+
+ const networkId = chain.getConfiguration().id
+ const nftsForChain = get(selectedAccountNfts).filter((nft) => nft.networkId === networkId)
+
+ const newNftIds = nftIds.filter((nftId) => !nftsForChain.some((nft) => nft.id === nftId))
+
+ const nfts = await getNftsFromNftIds(newNftIds, networkId)
+ addOrUpdateNftInAllAccountNfts(accountIndex, ...nfts)
+
+ const unspendableNftIds: string[] = nftsForChain
+ .filter((nft) => !nftIds.some((nftId) => nft.id === nftId))
+ .map((nft) => nft.id)
+ setNftInAllAccountNftsToUnspendable(accountIndex, ...unspendableNftIds)
+ void addNftsToDownloadQueue(accountIndex, nfts)
+ } catch (err) {
+ console.error(err)
+ }
+}
diff --git a/packages/shared/src/lib/core/layer-2/actions/getLayer2MetadataForTransfer.ts b/packages/shared/src/lib/core/layer-2/actions/getLayer2MetadataForTransfer.ts
index 610209438a..c00de2c127 100644
--- a/packages/shared/src/lib/core/layer-2/actions/getLayer2MetadataForTransfer.ts
+++ b/packages/shared/src/lib/core/layer-2/actions/getLayer2MetadataForTransfer.ts
@@ -5,7 +5,7 @@ import { SpecialStream } from '../classes'
import { ACCOUNTS_CONTRACT, EXTERNALLY_OWNED_ACCOUNT, GAS_LIMIT_MULTIPLIER, TRANSFER_ALLOWANCE } from '../constants'
import { encodeAddress, encodeAssetAllowance, encodeSmartContractParameters } from '../helpers'
import { estimateGasForLayer1ToLayer2Transaction } from './estimateGasForLayer1ToLayer2Transaction'
-import { EvmChainId, getChainConfiguration } from '@core/network'
+import { getChainConfiguration } from '@core/network'
export async function getLayer2MetadataForTransfer(sendFlowParameters: SendFlowParameters): Promise {
const metadataStream = new SpecialStream()
@@ -21,17 +21,12 @@ export async function getLayer2MetadataForTransfer(sendFlowParameters: SendFlowP
const estimatedGas = await estimateGasForLayer1ToLayer2Transaction(sendFlowParameters as TokenSendFlowParameters)
const gasLimit = Math.floor(estimatedGas * GAS_LIMIT_MULTIPLIER)
- // TODO: use writeUInt8 once EVM Testnet encoding reaches parity with ShimmerEVM
- if (chainConfig.chainId === EvmChainId.ShimmerEvmTestnet) {
- metadataStream.writeUInt32('senderContract', EXTERNALLY_OWNED_ACCOUNT)
- } else {
- metadataStream.writeUInt8('senderContract', EXTERNALLY_OWNED_ACCOUNT)
- }
+ metadataStream.writeUInt8('senderContract', EXTERNALLY_OWNED_ACCOUNT)
metadataStream.writeUInt32('targetContract', ACCOUNTS_CONTRACT)
metadataStream.writeUInt32('contractFunction', TRANSFER_ALLOWANCE)
// Gas budget is the ISC equivalent of gas limit in ethereum and what we use throughout the code
- metadataStream.writeUInt64SpecialEncoding('gasBudget', BigInteger(gasLimit))
+ metadataStream.writeUInt64SpecialEncoding('gasLimit', BigInteger(gasLimit))
const smartContractParameters = Object.entries({ a: encodedAddress })
const parameters = encodeSmartContractParameters(smartContractParameters)
diff --git a/packages/shared/src/lib/core/layer-2/actions/index.ts b/packages/shared/src/lib/core/layer-2/actions/index.ts
index 3990ec8582..387837f82b 100644
--- a/packages/shared/src/lib/core/layer-2/actions/index.ts
+++ b/packages/shared/src/lib/core/layer-2/actions/index.ts
@@ -3,7 +3,7 @@ export * from './buildUnwrapAssetParameters'
export * from './buildUnwrapAssetTargetAddress'
export * from './canAccountMakeEvmTransaction'
export * from './estimateGasForLayer1ToLayer2Transaction'
-export * from './fetchSelectedAccountLayer2Balance'
+export * from './fetchLayer2BalanceForAccount'
export * from './generateAndStoreEvmAddressForAccounts'
export * from './getGasFeesForLayer1ToLayer2Transaction'
export * from './getGasPriceForNetwork'
diff --git a/packages/shared/src/lib/core/layer-2/actions/pollLayer2Tokens.ts b/packages/shared/src/lib/core/layer-2/actions/pollLayer2Tokens.ts
index 9d105eeeba..38c7611a17 100644
--- a/packages/shared/src/lib/core/layer-2/actions/pollLayer2Tokens.ts
+++ b/packages/shared/src/lib/core/layer-2/actions/pollLayer2Tokens.ts
@@ -1,14 +1,14 @@
import { LAYER2_TOKENS_POLL_INTERVAL } from '../constants'
-import { fetchSelectedAccountLayer2Balance } from '.'
+import { fetchLayer2BalanceForAccount } from '.'
import { IAccountState } from '@core/account'
let pollInterval: number
export function pollLayer2Tokens(account: IAccountState): void {
clearLayer2TokensPoll()
- fetchSelectedAccountLayer2Balance(account)
+ fetchLayer2BalanceForAccount(account)
pollInterval = window.setInterval(() => {
- fetchSelectedAccountLayer2Balance(account)
+ fetchLayer2BalanceForAccount(account)
}, LAYER2_TOKENS_POLL_INTERVAL)
}
diff --git a/packages/shared/src/lib/core/layer-2/helpers/evmAddressToAgentId.ts b/packages/shared/src/lib/core/layer-2/helpers/evmAddressToAgentId.ts
index 8f4119e3ec..8579ddab50 100644
--- a/packages/shared/src/lib/core/layer-2/helpers/evmAddressToAgentId.ts
+++ b/packages/shared/src/lib/core/layer-2/helpers/evmAddressToAgentId.ts
@@ -1,5 +1,5 @@
import { EXTERNALLY_OWNED_ACCOUNT_TYPE_ID } from '@core/layer-2/constants'
-import { ChainConfiguration, ChainType, SupportedNetworkId } from '@core/network'
+import { ChainConfiguration, ChainType } from '@core/network'
import { api } from '@core/profile-manager'
import { Converter } from '@iota/util.js'
@@ -15,12 +15,7 @@ export function evmAddressToAgentId(evmStoreAccount: string, chainConfig: ChainC
// otherwise fetching balances using the iscmagic contract will fail,
// because evm addresses are case-insensitive but hexToBytes is not.
const receiverAddrBinary = Converter.hexToBytes(evmStoreAccount?.toLowerCase())
+ const chainAliasAddressBinary = Converter.hexToBytes(api.bech32ToHex(chainAliasAddress))
- // Keep the branch with chainAliasAddressBinary once IF updates the encoding for the EVM testnet
- if (chainConfig.id === SupportedNetworkId.ShimmerEvmTestnet) {
- return new Uint8Array([agentIDKindEthereumAddress, ...receiverAddrBinary])
- } else {
- const chainAliasAddressBinary = Converter.hexToBytes(api.bech32ToHex(chainAliasAddress))
- return new Uint8Array([agentIDKindEthereumAddress, ...chainAliasAddressBinary, ...receiverAddrBinary])
- }
+ return new Uint8Array([agentIDKindEthereumAddress, ...chainAliasAddressBinary, ...receiverAddrBinary])
}
diff --git a/packages/shared/src/lib/core/layer-2/tests/parseLayer2MetadataForTransfer.test.ts b/packages/shared/src/lib/core/layer-2/tests/parseLayer2MetadataForTransfer.test.ts
index cd9c4408c9..3457166cad 100644
--- a/packages/shared/src/lib/core/layer-2/tests/parseLayer2MetadataForTransfer.test.ts
+++ b/packages/shared/src/lib/core/layer-2/tests/parseLayer2MetadataForTransfer.test.ts
@@ -3,7 +3,7 @@ import { parseLayer2MetadataForTransfer } from '../utils/parseLayer2MetadataForT
describe('Function: parseLayer2MetadataForTransfer.ts', () => {
it('should correctly parse metadata with base token', () => {
- const metadata = '0x00000000025e4b3ca1e3f423a0c21e0101611503807d707f59f1345e1063dbb64f2495d1491283a080c0843d'
+ const metadata = '0x00025e4b3ca1e3f423a0c21e0101611503807d707f59f1345e1063dbb64f2495d1491283a080c0843d'
const metadataByteArray = Converter.hexToBytes(metadata)
const expected = {
senderContract: '0x0',
@@ -21,7 +21,7 @@ describe('Function: parseLayer2MetadataForTransfer.ts', () => {
it('should correctly parse metadata with native tokens', () => {
const metadata =
- '0x00000000025e4b3ca1e3f423a0c21e01016115038cc8112290f8c350a60e1afdb8379c686e2a5bb3400108fcccc313acc182fc2c647dc98864062b163a8ee254231d7f029dc6be3a2de52e01000000000132'
+ '0x00025e4b3ca1e3f423a0c21e01016115038cc8112290f8c350a60e1afdb8379c686e2a5bb3400108fcccc313acc182fc2c647dc98864062b163a8ee254231d7f029dc6be3a2de52e01000000000132'
const metadataByteArray = Converter.hexToBytes(metadata)
const expected = {
senderContract: '0x0',
@@ -44,7 +44,7 @@ describe('Function: parseLayer2MetadataForTransfer.ts', () => {
it('should correctly parse metadata with nfts', () => {
const metadata =
- '0x00000000025e4b3ca1e3f423a0c21e0101611503cbcd6d8659ed1998a452335ae53904dc0af1c99b200166b71141974aa368c9152a24d631494b46172ba05dd998eef553e7fa1218b704'
+ '0x00025e4b3ca1e3f423a0c21e0101611503cbcd6d8659ed1998a452335ae53904dc0af1c99b200166b71141974aa368c9152a24d631494b46172ba05dd998eef553e7fa1218b704'
const metadataByteArray = Converter.hexToBytes(metadata)
const expected = {
senderContract: '0x0',
diff --git a/packages/shared/src/lib/core/layer-2/utils/parseLayer2MetadataForTransfer.ts b/packages/shared/src/lib/core/layer-2/utils/parseLayer2MetadataForTransfer.ts
index c1bdf545df..55f34cbcd7 100644
--- a/packages/shared/src/lib/core/layer-2/utils/parseLayer2MetadataForTransfer.ts
+++ b/packages/shared/src/lib/core/layer-2/utils/parseLayer2MetadataForTransfer.ts
@@ -6,10 +6,9 @@ import { Converter, HEX_PREFIX } from '@core/utils'
import { CONTRACT_FUNCTIONS, TARGET_CONTRACTS } from '../constants'
import { ILayer2AssetAllowance, ILayer2TransferAllowanceMetadata } from '../interfaces'
-// Function to parse data from the L1 metadata, using the new encoding where the shimmer chainId is 1072
export function parseLayer2MetadataForTransfer(metadata: Uint8Array): ILayer2TransferAllowanceMetadata {
const readStream = new ReadSpecialStream(metadata)
- const senderContract = readStream.readUInt32('senderContract')
+ const senderContract = readStream.readUInt8('senderContract')
const targetContract = readStream.readUInt32('targetContract')
const contractFunction = readStream.readUInt32('contractFunction')
// TODO: This is a temporary fix since now the gas is always 500000, when it varies, the length of the gas will change
diff --git a/packages/shared/src/lib/core/network/constants/default-chain-configurations.constant.ts b/packages/shared/src/lib/core/network/constants/default-chain-configurations.constant.ts
index 0ad4048505..bc8b370399 100644
--- a/packages/shared/src/lib/core/network/constants/default-chain-configurations.constant.ts
+++ b/packages/shared/src/lib/core/network/constants/default-chain-configurations.constant.ts
@@ -12,7 +12,7 @@ export const DEFAULT_CHAIN_CONFIGURATIONS: Readonly<{ [id in NetworkId]?: ChainC
coinType: DEFAULT_COIN_TYPE[SupportedNetworkId.ShimmerEvm],
aliasAddress: 'smr1prxvwqvwf7nru5q5xvh5thwg54zsm2y4wfnk6yk56hj3exxkg92mx20wl3s',
iscpEndpoint: 'https://json-rpc.evm.shimmer.network/',
- explorerUrl: 'https://explorer.evm.shimmer.network',
+ explorerUrl: 'https://explorer.evm.shimmer.network/',
},
[SupportedNetworkId.Testnet]: {
id: SupportedNetworkId.ShimmerEvmTestnet,
@@ -21,8 +21,8 @@ export const DEFAULT_CHAIN_CONFIGURATIONS: Readonly<{ [id in NetworkId]?: ChainC
chainId: EvmChainId.ShimmerEvmTestnet,
namespace: NetworkNamespace.Evm,
coinType: DEFAULT_COIN_TYPE[SupportedNetworkId.ShimmerEvmTestnet],
- aliasAddress: 'rms1pr75wa5xuepg2hew44vnr28wz5h6n6x99zptk2g68sp2wuu2karywgrztx3',
- iscpEndpoint: 'https://json-rpc.evm.testnet.shimmer.network',
- explorerUrl: 'https://explorer.evm.testnet.shimmer.network',
+ aliasAddress: 'rms1ppp00k5mmd2m8my8ukkp58nd3rskw6rx8l09aj35984k74uuc5u2cywn3ex',
+ iscpEndpoint: 'https://json-rpc.evm.testnet.shimmer.network/',
+ explorerUrl: 'https://explorer.evm.testnet.shimmer.network/',
},
}
diff --git a/packages/shared/src/lib/core/network/constants/default-explorer-urls.constant.ts b/packages/shared/src/lib/core/network/constants/default-explorer-urls.constant.ts
index 3c635cbf3d..f5959752e0 100644
--- a/packages/shared/src/lib/core/network/constants/default-explorer-urls.constant.ts
+++ b/packages/shared/src/lib/core/network/constants/default-explorer-urls.constant.ts
@@ -4,6 +4,6 @@ import { NetworkId } from '../types'
export const DEFAULT_EXPLORER_URLS: Readonly<{ [key in NetworkId]?: string }> = {
[SupportedNetworkId.Shimmer]: 'https://explorer.shimmer.network/shimmer',
[SupportedNetworkId.Testnet]: 'https://explorer.shimmer.network/testnet',
- [SupportedNetworkId.ShimmerEvm]: '',
+ [SupportedNetworkId.ShimmerEvm]: 'https://explorer.evm.shimmer.network/',
[SupportedNetworkId.ShimmerEvmTestnet]: 'https://explorer.evm.testnet.shimmer.network',
}
diff --git a/packages/shared/src/lib/core/network/enums/evm-chain-id.enum.ts b/packages/shared/src/lib/core/network/enums/evm-chain-id.enum.ts
index 5525bdaad0..b5acf651f0 100644
--- a/packages/shared/src/lib/core/network/enums/evm-chain-id.enum.ts
+++ b/packages/shared/src/lib/core/network/enums/evm-chain-id.enum.ts
@@ -1,4 +1,4 @@
export enum EvmChainId {
ShimmerEvm = '148',
- ShimmerEvmTestnet = '1072',
+ ShimmerEvmTestnet = '1073',
}
diff --git a/packages/shared/src/lib/core/network/enums/stardust-network-name.enum.ts b/packages/shared/src/lib/core/network/enums/stardust-network-name.enum.ts
index 4461fe67d0..3b94c53f7e 100644
--- a/packages/shared/src/lib/core/network/enums/stardust-network-name.enum.ts
+++ b/packages/shared/src/lib/core/network/enums/stardust-network-name.enum.ts
@@ -1,4 +1,4 @@
export enum StardustNetworkName {
Shimmer = 'shimmer',
- Testnet = 'testnet-1',
+ Testnet = 'testnet-2',
}
diff --git a/packages/shared/src/lib/core/nfts/actions/addOrUpdateNftInAllAccountNfts.ts b/packages/shared/src/lib/core/nfts/actions/addOrUpdateNftInAllAccountNfts.ts
index ca85816545..0b1502ab10 100644
--- a/packages/shared/src/lib/core/nfts/actions/addOrUpdateNftInAllAccountNfts.ts
+++ b/packages/shared/src/lib/core/nfts/actions/addOrUpdateNftInAllAccountNfts.ts
@@ -1,16 +1,18 @@
import { allAccountNfts } from '../stores'
import { INft } from '../interfaces'
-export function addOrUpdateNftInAllAccountNfts(accountIndex: number, newNft: INft): void {
+export function addOrUpdateNftInAllAccountNfts(accountIndex: number, ...newNfts: INft[]): void {
allAccountNfts.update((state) => {
if (!state[accountIndex]) {
state[accountIndex] = []
}
- const nft = state[accountIndex].find((_nft) => _nft.id === newNft.id)
- if (nft) {
- Object.assign(nft, newNft)
- } else {
- state[accountIndex].push(newNft)
+ for (const newNft of newNfts) {
+ const nft = state[accountIndex].find((_nft) => _nft.id === newNft.id)
+ if (nft) {
+ Object.assign(nft, newNft)
+ } else {
+ state[accountIndex].push(newNft)
+ }
}
return state
})
diff --git a/packages/shared/src/lib/core/nfts/actions/buildNftFromNftOutput.ts b/packages/shared/src/lib/core/nfts/actions/buildNftFromNftOutput.ts
index a3e6304305..96c0bbb41a 100644
--- a/packages/shared/src/lib/core/nfts/actions/buildNftFromNftOutput.ts
+++ b/packages/shared/src/lib/core/nfts/actions/buildNftFromNftOutput.ts
@@ -7,10 +7,12 @@ import { get } from 'svelte/store'
import { DEFAULT_NFT_NAME } from '../constants'
import { INft } from '../interfaces'
import { composeUrlFromNftUri, getSpendableStatusFromUnspentNftOutput, parseNftMetadata } from '../utils'
-import { getActiveNetworkId } from '@core/network'
+import { NetworkId } from '@core/network/types'
+import { isEvmChain } from '@core/network'
export function buildNftFromNftOutput(
wrappedOutput: IWrappedOutput,
+ networkId: NetworkId,
accountAddress: string,
calculateStatus: boolean = true
): INft {
@@ -40,7 +42,7 @@ export function buildNftFromNftOutput(
address,
name: parsedMetadata?.name ?? DEFAULT_NFT_NAME,
issuer,
- isSpendable,
+ isSpendable: isEvmChain(networkId) ? true : isSpendable,
timelockTime: timeLockTime ? Number(timeLockTime) : undefined,
metadata,
parsedMetadata,
@@ -49,7 +51,7 @@ export function buildNftFromNftOutput(
downloadUrl: composedUrl,
filePath,
storageDeposit,
- networkId: getActiveNetworkId(),
+ networkId,
downloadMetadata: {
error: undefined,
warning: undefined,
diff --git a/packages/shared/src/lib/core/nfts/actions/index.ts b/packages/shared/src/lib/core/nfts/actions/index.ts
index ee6ec154b0..973abde7b4 100644
--- a/packages/shared/src/lib/core/nfts/actions/index.ts
+++ b/packages/shared/src/lib/core/nfts/actions/index.ts
@@ -6,5 +6,6 @@ export * from './getNftByIdFromAllAccountNfts'
export * from './interruptNftDownloadAfterTimeout'
export * from './loadNftsForActiveProfile'
export * from './setAccountNftsInAllAccountNfts'
+export * from './setNftInAllAccountNftsToUnspendable'
export * from './stopDownloadingNftMediaFromQueue'
export * from './updateNftInAllAccountNfts'
diff --git a/packages/shared/src/lib/core/nfts/actions/loadNftsForActiveProfile.ts b/packages/shared/src/lib/core/nfts/actions/loadNftsForActiveProfile.ts
index 0fa18f95b6..3d7cf73cd0 100644
--- a/packages/shared/src/lib/core/nfts/actions/loadNftsForActiveProfile.ts
+++ b/packages/shared/src/lib/core/nfts/actions/loadNftsForActiveProfile.ts
@@ -7,20 +7,22 @@ import { get } from 'svelte/store'
import { INft } from '../interfaces'
import { buildNftFromNftOutput } from './buildNftFromNftOutput'
import { setAccountNftsInAllAccountNfts } from './setAccountNftsInAllAccountNfts'
+import { NetworkId, getActiveNetworkId } from '@core/network'
export async function loadNftsForActiveProfile(): Promise {
const allAccounts = get(activeAccounts)
+ const networkId = getActiveNetworkId()
for (const account of allAccounts) {
- await loadNftsForAccount(account)
+ await loadNftsForAccount(account, networkId)
}
}
-async function loadNftsForAccount(account: IAccountState): Promise {
+async function loadNftsForAccount(account: IAccountState, networkId: NetworkId): Promise {
const accountNfts: INft[] = []
const unspentOutputs = await account.unspentOutputs()
for (const outputData of unspentOutputs) {
if (outputData.output.type === OutputType.Nft) {
- const nft = buildNftFromNftOutput(outputData as IWrappedOutput, account.depositAddress)
+ const nft = buildNftFromNftOutput(outputData as IWrappedOutput, networkId, account.depositAddress)
accountNfts.push(nft)
}
}
@@ -34,7 +36,12 @@ async function loadNftsForAccount(account: IAccountState): Promise {
const nftOutput = outputData.output as NftOutput
const nftId = getNftId(nftOutput.nftId, outputData.outputId)
if (!accountNfts.some((nft) => nft.id === nftId)) {
- const nft = buildNftFromNftOutput(outputData as IWrappedOutput, account.depositAddress, false)
+ const nft = buildNftFromNftOutput(
+ outputData as IWrappedOutput,
+ networkId,
+ account.depositAddress,
+ false
+ )
accountNfts.push(nft)
}
}
diff --git a/packages/shared/src/lib/core/nfts/actions/setNftInAllAccountNftsToUnspendable.ts b/packages/shared/src/lib/core/nfts/actions/setNftInAllAccountNftsToUnspendable.ts
new file mode 100644
index 0000000000..42f8f37979
--- /dev/null
+++ b/packages/shared/src/lib/core/nfts/actions/setNftInAllAccountNftsToUnspendable.ts
@@ -0,0 +1,17 @@
+import { allAccountNfts } from '../stores'
+
+export function setNftInAllAccountNftsToUnspendable(accountIndex: number, ...unspendableNftIds: string[]): void {
+ allAccountNfts.update((state) => {
+ if (!state[accountIndex]) {
+ state[accountIndex] = []
+ }
+ for (const nftId of unspendableNftIds) {
+ const nft = state[accountIndex].find((_nft) => _nft.id === nftId)
+ if (nft) {
+ nft.isSpendable = false
+ Object.assign(nft, nft)
+ }
+ }
+ return state
+ })
+}
diff --git a/packages/shared/src/lib/core/nfts/interfaces/nft.interface.ts b/packages/shared/src/lib/core/nfts/interfaces/nft.interface.ts
index 5ff7367049..3e0ed9d734 100644
--- a/packages/shared/src/lib/core/nfts/interfaces/nft.interface.ts
+++ b/packages/shared/src/lib/core/nfts/interfaces/nft.interface.ts
@@ -11,7 +11,7 @@ export interface INft {
issuer?: Address
parsedMetadata?: IIrc27Metadata
isSpendable: boolean
- timelockTime: number
+ timelockTime?: number
latestOutputId: string
composedUrl: string
downloadUrl: string
diff --git a/packages/shared/src/lib/core/nfts/tests/buildNftFromNftOutput.test.ts b/packages/shared/src/lib/core/nfts/tests/buildNftFromNftOutput.test.ts
index f6fd9db39f..eb1ecac67f 100644
--- a/packages/shared/src/lib/core/nfts/tests/buildNftFromNftOutput.test.ts
+++ b/packages/shared/src/lib/core/nfts/tests/buildNftFromNftOutput.test.ts
@@ -13,6 +13,7 @@ import { buildNftFromNftOutput } from '../actions/buildNftFromNftOutput'
import { NetworkNamespace, StardustNetworkName } from '../../network/enums'
const accountAddress = 'rms1qr47ee0fhahukrzec088v9lngv7w5k2sn3jjtwvkcpjfgxhhsazlsurxrx9'
+const networkId = `${NetworkNamespace.Stardust}:${StardustNetworkName.Shimmer}`
const outputId = '0x16cc2007c1f0120b4832f89950ac5099f804c9730f54c4c1865f485b7b12a7870000'
const type = 6
@@ -55,7 +56,7 @@ jest.mock('../../../../lib/core/wallet/utils/getBech32AddressFromAddressTypes.ts
jest.mock('../../network/actions/getActiveNetworkId.ts', () => ({
getActiveNetworkId: jest.fn(() => {
- return `${NetworkNamespace.Stardust}:${StardustNetworkName.Shimmer}`
+ return networkId
}),
}))
@@ -73,7 +74,7 @@ describe('File: buildNFtFromOutput.ts', () => {
immutableFeatures,
},
}
- let nft = buildNftFromNftOutput(outputData, accountAddress, true)
+ let nft = buildNftFromNftOutput(outputData, networkId, accountAddress, true)
expect(nft.isSpendable).toBe(true)
})
@@ -88,7 +89,7 @@ describe('File: buildNFtFromOutput.ts', () => {
immutableFeatures,
},
}
- const nft = buildNftFromNftOutput(outputData, accountAddress)
+ const nft = buildNftFromNftOutput(outputData, networkId, accountAddress)
expect(nft.isSpendable).toBe(true)
expect(nft.timelockTime).toBe(2876367917000)
})
@@ -104,7 +105,7 @@ describe('File: buildNFtFromOutput.ts', () => {
immutableFeatures,
},
}
- const nft = buildNftFromNftOutput(outputData, accountAddress)
+ const nft = buildNftFromNftOutput(outputData, networkId, accountAddress)
expect(nft.isSpendable).toBe(true)
expect(nft.timelockTime).toBe(136367917000)
})
@@ -119,7 +120,7 @@ describe('File: buildNFtFromOutput.ts', () => {
unlockConditions: incomingUnlockConditions,
},
}
- let nft = buildNftFromNftOutput(outputData, accountAddress, false)
+ let nft = buildNftFromNftOutput(outputData, networkId, accountAddress, false)
expect(nft.isSpendable).toBe(false)
expect(nft.timelockTime).toBe(undefined)
@@ -132,7 +133,7 @@ describe('File: buildNFtFromOutput.ts', () => {
unlockConditions: incomingTimelockedCondition,
},
}
- nft = buildNftFromNftOutput(outputData, accountAddress, false)
+ nft = buildNftFromNftOutput(outputData, networkId, accountAddress, false)
expect(nft.isSpendable).toBe(false)
expect(nft.timelockTime).toBe(undefined)
@@ -146,7 +147,7 @@ describe('File: buildNFtFromOutput.ts', () => {
immutableFeatures,
},
}
- nft = buildNftFromNftOutput(outputData, accountAddress, false)
+ nft = buildNftFromNftOutput(outputData, networkId, accountAddress, false)
expect(nft.isSpendable).toBe(false)
expect(nft.timelockTime).toBe(undefined)
})
@@ -162,7 +163,7 @@ describe('File: buildNFtFromOutput.ts', () => {
immutableFeatures,
},
}
- let nft = buildNftFromNftOutput(outputData, accountAddress)
+ let nft = buildNftFromNftOutput(outputData, networkId, accountAddress)
let expectedParsedMetadata = {
standard: 'IRC27',
diff --git a/packages/shared/src/lib/core/nfts/utils/getNftsFromNftIds.ts b/packages/shared/src/lib/core/nfts/utils/getNftsFromNftIds.ts
new file mode 100644
index 0000000000..653366379a
--- /dev/null
+++ b/packages/shared/src/lib/core/nfts/utils/getNftsFromNftIds.ts
@@ -0,0 +1,41 @@
+import type { NftOutput, OutputResponse } from '@iota/sdk'
+import { buildNftFromNftOutput } from '../actions'
+import { INft } from '../interfaces'
+import { getClient } from '@core/profile-manager'
+import { getOutputIdFromTransactionIdAndIndex } from '@core/activity'
+import { NetworkId } from '@core/network/types'
+
+export async function getNftsFromNftIds(nftIds: string[], networkId: NetworkId): Promise {
+ const client = await getClient()
+ const nftOutputIds = []
+ for (const nftId of nftIds) {
+ try {
+ const nftOutputId = await client.nftOutputId(nftId)
+ if (nftOutputId) {
+ nftOutputIds.push(nftOutputId)
+ }
+ } catch (err) {
+ console.error(err, nftId)
+ }
+ }
+
+ let outputs: OutputResponse[] = []
+ try {
+ outputs = await client.getOutputs(nftOutputIds)
+ } catch (err) {
+ outputs = []
+ console.error(err)
+ }
+
+ const nfts: INft[] = []
+ for (const nftOutput of outputs) {
+ const outputId = getOutputIdFromTransactionIdAndIndex(
+ nftOutput.metadata.transactionId,
+ nftOutput.metadata.outputIndex
+ )
+ const wrappedOutput = { outputId, output: nftOutput.output as NftOutput }
+ const nft = buildNftFromNftOutput(wrappedOutput, networkId, '', false)
+ nfts.push(nft)
+ }
+ return nfts
+}
diff --git a/packages/shared/src/lib/core/nfts/utils/index.ts b/packages/shared/src/lib/core/nfts/utils/index.ts
index 6db8ae82fe..8460daabd3 100644
--- a/packages/shared/src/lib/core/nfts/utils/index.ts
+++ b/packages/shared/src/lib/core/nfts/utils/index.ts
@@ -1,6 +1,7 @@
export * from './checkIfNftShouldBeDownloaded'
export * from './composeUrlFromNftUri'
export * from './convertAndFormatNftMetadata'
+export * from './getNftsFromNftIds'
export * from './getSpendableStatusFromUnspentNftOutput'
export * from './fetchWithTimeout'
export * from './isNftOwnedByAnyAccount'
diff --git a/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleNewOutputEvent.ts b/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleNewOutputEvent.ts
index bfde611f26..558f14b062 100644
--- a/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleNewOutputEvent.ts
+++ b/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleNewOutputEvent.ts
@@ -30,7 +30,7 @@ export async function handleNewOutputEventInternal(
const networkId = getActiveNetworkId()
const output = walletEvent?.output
- if (!account || !output || !networkId) return
+ if (!account || !output) return
const address = getBech32AddressFromAddressTypes(output?.address)
const outputData = output.output as AliasOutput
@@ -57,7 +57,7 @@ export async function handleNewOutputEventInternal(
}
if (isNftOutput) {
- const nft = buildNftFromNftOutput(output as IWrappedOutput, account.depositAddress)
+ const nft = buildNftFromNftOutput(output as IWrappedOutput, networkId, account.depositAddress)
addOrUpdateNftInAllAccountNfts(account.index, nft)
void addNftsToDownloadQueue(accountIndex, [nft])
diff --git a/packages/shared/src/lib/core/token/tests/convertToRawAmount.test.ts b/packages/shared/src/lib/core/token/tests/convertToRawAmount.test.ts
index 616a5f1864..b93f47b34a 100644
--- a/packages/shared/src/lib/core/token/tests/convertToRawAmount.test.ts
+++ b/packages/shared/src/lib/core/token/tests/convertToRawAmount.test.ts
@@ -53,8 +53,9 @@ describe('File: convertToRawAmount.ts', () => {
it('should return same Big(amount) if selectedUnit is subunit', () => {
expect(convertToRawAmount('1', DEFAULT_BASE_TOKEN[networkId], 'glow')).toStrictEqual(Big('1'))
})
- it('should return undefined if a unit is not provided', () => {
- expect(convertToRawAmount('1', DEFAULT_BASE_TOKEN[networkId])).toStrictEqual(undefined)
+ it('should return tokens unit if no unit is provided', () => {
+ let value = convertToRawAmount('1', DEFAULT_BASE_TOKEN[networkId])
+ expect(value).toStrictEqual(Big('1').mul(Big(10).pow(DEFAULT_BASE_TOKEN[networkId].decimals)))
})
it('should return undefined if provided unit does not match the tokenMetadata unit or subunit', () => {
expect(convertToRawAmount('1', DEFAULT_BASE_TOKEN[networkId], 'test')).toStrictEqual(undefined)
diff --git a/packages/shared/src/lib/core/token/utils/convertToRawAmount.ts b/packages/shared/src/lib/core/token/utils/convertToRawAmount.ts
index 8762ec2ed3..0ac23d074e 100644
--- a/packages/shared/src/lib/core/token/utils/convertToRawAmount.ts
+++ b/packages/shared/src/lib/core/token/utils/convertToRawAmount.ts
@@ -24,7 +24,7 @@ function convertToRawAmountFromMetadata(
const decimals = IOTA_UNIT_MAP?.[selectedUnit?.substring(0, 1) as IotaUnit]?.decimalPlaces ?? 0
return convertAmountToMatchUnit(amount, decimals)
} else {
- if (selectedUnit === tokenMetadata.unit) {
+ if (!selectedUnit || selectedUnit === tokenMetadata.unit) {
const decimals = Math.min(tokenMetadata.decimals, MAX_SUPPORTED_DECIMALS)
return convertAmountToMatchUnit(amount, decimals)
} else if (selectedUnit === tokenMetadata.subunit) {
diff --git a/packages/shared/src/lib/core/wallet/actions/mintNft.ts b/packages/shared/src/lib/core/wallet/actions/mintNft.ts
index d4c4e172ec..4519506edd 100644
--- a/packages/shared/src/lib/core/wallet/actions/mintNft.ts
+++ b/packages/shared/src/lib/core/wallet/actions/mintNft.ts
@@ -52,7 +52,7 @@ export async function mintNft(metadata: IIrc27Metadata, quantity: number): Promi
addActivityToAccountActivitiesInAllAccountActivities(account.index, activity)
// Store NFT metadata for each minted NFT
- const nft = buildNftFromNftOutput(output, account.depositAddress, false)
+ const nft = buildNftFromNftOutput(output, networkId, account.depositAddress, false)
addOrUpdateNftInAllAccountNfts(account.index, nft)
}
}
diff --git a/packages/shared/src/lib/core/wallet/actions/send/createEvmChainToEvmChainTransaction.ts b/packages/shared/src/lib/core/wallet/actions/send/createEvmChainToEvmChainTransaction.ts
index ab19dc9212..a647ef2e8c 100644
--- a/packages/shared/src/lib/core/wallet/actions/send/createEvmChainToEvmChainTransaction.ts
+++ b/packages/shared/src/lib/core/wallet/actions/send/createEvmChainToEvmChainTransaction.ts
@@ -12,17 +12,14 @@ import { IToken } from '@core/token/interfaces'
import { SendFlowType } from '../../enums'
import { SendFlowParameters } from '../../types'
import { getAmountAndTokenFromSendFlowParameters } from '../../utils/send/getAmountAndTokenFromSendFlowParameters'
+import { INft } from '@core/nfts/interfaces'
export function createEvmChainToEvmChainTransaction(
sendFlowParameters: SendFlowParameters,
chain: IChain,
account: IAccountState
): Promise {
- if (
- !sendFlowParameters ||
- sendFlowParameters.type === SendFlowType.NftTransfer ||
- !sendFlowParameters.recipient?.address
- ) {
+ if (!sendFlowParameters || !sendFlowParameters.recipient?.address) {
throw new Error(localize('error.send.invalidSendParameters'))
}
@@ -31,15 +28,6 @@ export function createEvmChainToEvmChainTransaction(
throw new Error(localize('error.web3.unableToFindProvider'))
}
- let { token, amount } = getAmountAndTokenFromSendFlowParameters(sendFlowParameters)
- if (!token?.metadata) {
- throw new Error(localize('error.token.missingMetadata'))
- }
-
- if (amount === undefined) {
- throw new Error(localize('error.send.amountInvalidFormat'))
- }
-
const recipientAddress = sendFlowParameters.recipient.address
const { evmAddresses } = account
@@ -48,42 +36,73 @@ export function createEvmChainToEvmChainTransaction(
throw new Error(localize('error.send.unableToGetOriginAddress'))
}
- const destinationAddress = getDestinationAddress(token, recipientAddress)
+ let token: IToken | undefined
+ let amount: string | undefined
+ let nft: INft | undefined
+ let destinationAddress: string | undefined
- let data: string | undefined
- if (!token || token.metadata?.standard === TokenStandard.BaseToken) {
- data = undefined
+ if (
+ sendFlowParameters.type === SendFlowType.TokenTransfer ||
+ sendFlowParameters.type === SendFlowType.BaseCoinTransfer
+ ) {
+ const tokenAmount = getAmountAndTokenFromSendFlowParameters(sendFlowParameters)
+ token = tokenAmount.token
+ amount = tokenAmount.amount
+
+ if (!token?.metadata) {
+ throw new Error(localize('error.token.missingMetadata'))
+ }
+
+ if (amount === undefined) {
+ throw new Error(localize('error.send.amountInvalidFormat'))
+ }
+
+ destinationAddress = getDestinationAddress(token, recipientAddress)
} else {
- data = getDataForTransaction(chain, recipientAddress, token, amount)
+ nft = sendFlowParameters.nft
+ destinationAddress = ISC_MAGIC_CONTRACT_ADDRESS
+ }
+
+ let data: string | undefined
+ if (token?.standard === TokenStandard.Irc30 || token?.standard === TokenStandard.Erc20 || nft) {
+ data = getDataForTransaction(chain, recipientAddress, token, amount, nft)
// set amount to zero after using it to build the smart contract data,
// as we do not want to send any base token
amount = '0'
if (!data) {
throw new Error(localize('error.web3.unableToFormSmartContractData'))
}
+ } else {
+ data = undefined
}
- return buildEvmTransactionData(provider, originAddress, destinationAddress, amount, data)
+ return buildEvmTransactionData(provider, originAddress, destinationAddress, amount ?? '0', data)
}
function getDataForTransaction(
chain: IChain,
recipientAddress: string,
- token: IToken,
- amount: string
+ token: IToken | undefined,
+ amount: string | undefined,
+ nft: INft | undefined
): string | undefined {
- const standard = token.metadata?.standard
- switch (standard) {
- case TokenStandard.Irc30: {
- const isBaseCoin = token.standard === TokenStandard.BaseToken
- const assetType = isBaseCoin ? AssetType.BaseCoin : AssetType.Token
- const transferredAsset = { type: assetType, token, amount } as TransferredAsset
- return getIscpTransferSmartContractData(recipientAddress, transferredAsset, chain)
+ if (token && amount) {
+ const standard = token.metadata?.standard
+ switch (standard) {
+ case TokenStandard.Irc30: {
+ const isBaseCoin = token.standard === TokenStandard.BaseToken
+ const assetType = isBaseCoin ? AssetType.BaseCoin : AssetType.Token
+ const transferredAsset = { type: assetType, token, amount } as TransferredAsset
+ return getIscpTransferSmartContractData(recipientAddress, transferredAsset, chain)
+ }
+ case TokenStandard.Erc20:
+ return getErc20TransferSmartContractData(recipientAddress, token, amount, chain)
+ default:
+ return undefined
}
- case TokenStandard.Erc20:
- return getErc20TransferSmartContractData(recipientAddress, token, amount, chain)
- default:
- return undefined
+ } else if (nft) {
+ const transferredAsset = { type: AssetType.Nft, nft } as TransferredAsset
+ return getIscpTransferSmartContractData(recipientAddress, transferredAsset, chain)
}
}
diff --git a/packages/shared/src/lib/core/wallet/tests/getOutputParameters.test.ts b/packages/shared/src/lib/core/wallet/tests/getOutputParameters.test.ts
index 1f261a1b85..38e1b6614d 100644
--- a/packages/shared/src/lib/core/wallet/tests/getOutputParameters.test.ts
+++ b/packages/shared/src/lib/core/wallet/tests/getOutputParameters.test.ts
@@ -1,5 +1,5 @@
import { activeProfileId } from '@core/profile/stores/active-profile-id.store'
-import { SupportedNetworkId, ChainId } from '@core/network/enums'
+import { SupportedNetworkId } from '@core/network/enums'
import { FALLBACK_ESTIMATED_GAS } from '@core/layer-2/constants'
import { DEFAULT_CHAIN_CONFIGURATIONS } from '@core/network/constants'
import { getOutputParameters } from '../utils'
@@ -237,7 +237,7 @@ describe('File: getOutputParameters.ts', () => {
amount: '1000000000',
features: {
metadata:
- '0x00000000025e4b3ca1e3f423fccf01010161200300010000070c000c30680e00000090000f0ea000060009000d300000000000808094ebdc03',
+ '0x00025e4b3ca1e3f423fccf01010161200300010000070c000c30680e00000090000f0ea000060009000d300000000000808094ebdc03',
sender: senderAddress,
},
unlocks: { expirationUnixTime: 1680163475 },
@@ -277,7 +277,7 @@ describe('File: getOutputParameters.ts', () => {
},
features: {
metadata:
- '0x00000000025e4b3ca1e3f423a1d101010161200300010000070c000c30680e00000090000f0ea000060009000d300000000000400108cd4dcad7ccc383111942671ee8cdc487ddd250398331ca2692b8b1a81551a1c30100000000043b9aca00',
+ '0x00025e4b3ca1e3f423a1d101010161200300010000070c000c30680e00000090000f0ea000060009000d300000000000400108cd4dcad7ccc383111942671ee8cdc487ddd250398331ca2692b8b1a81551a1c30100000000043b9aca00',
sender: senderAddress,
},
unlocks: { expirationUnixTime: 1680163475 },
@@ -303,7 +303,7 @@ describe('File: getOutputParameters.ts', () => {
},
features: {
metadata:
- '0x00000000025e4b3ca1e3f423a2d401010161200300010000070c000c30680e00000090000f0ea000060009000d3000000000002001cd9430ff870a22f81f92428e5c06975fa3ec1a993331aa3db9fb2298e931ade1',
+ '0x00025e4b3ca1e3f423a2d401010161200300010000070c000c30680e00000090000f0ea000060009000d3000000000002001cd9430ff870a22f81f92428e5c06975fa3ec1a993331aa3db9fb2298e931ade1',
sender: senderAddress,
},
unlocks: {},
diff --git a/packages/shared/src/lib/core/wallet/types/send-flow-parameter.type.ts b/packages/shared/src/lib/core/wallet/types/send-flow-parameter.type.ts
index 13b8148336..4f25abf284 100644
--- a/packages/shared/src/lib/core/wallet/types/send-flow-parameter.type.ts
+++ b/packages/shared/src/lib/core/wallet/types/send-flow-parameter.type.ts
@@ -18,6 +18,7 @@ export interface BaseSendFlowParameters {
addSenderFeature?: boolean
disableToggleGift?: boolean
disableChangeExpiration?: boolean
+ disableChangeTimelock?: boolean
baseCoinTransfer?: TokenTransferData
}
diff --git a/packages/shared/src/locales/en.json b/packages/shared/src/locales/en.json
index e778dcfc8f..da2b3c2ef5 100644
--- a/packages/shared/src/locales/en.json
+++ b/packages/shared/src/locales/en.json
@@ -477,10 +477,10 @@
"collectibles": {
"gallery": {
"title": "Collectibles",
- "emptyTitle": "No collectibles",
- "noResults": "No results",
+ "emptyTitle": "No collectibles found",
+ "noResults": "No results found",
"timelocked": "Locked for {timeDiff}",
- "emptyDescription": "Deposit or Receive your first collectible now!"
+ "emptyDescription": "Deposit or receive your first collectible!"
},
"details": {
"storageDepositDescription": "A refundable deposit required to store your NFT on the Tangle.",
@@ -1167,7 +1167,7 @@
"testDeepLink": "Test deep link",
"delete": "Delete",
"remove": "Remove",
- "depositNft": "Deposit NFTs",
+ "getStarted": "Get started",
"vote": "Vote",
"addProposal": "Add proposal",
"removeProposal": "Remove proposal",
@@ -1297,6 +1297,7 @@
"toAddress": "to {account}",
"capsLock": "Caps Lock is on",
"version": "Version",
+ "versionFull": "Version {version}",
"unknown": "Unknown",
"unknownAddress": "Unknown address",
"none": "None",
@@ -1888,7 +1889,7 @@
"notConnected": "Not connected",
"locked": "Device locked",
"appNotOpen": "App not open"
- }
+ }
},
"menus": {
"dateTimePicker": {
diff --git a/packages/shared/test/mocks/api.mock.ts b/packages/shared/test/mocks/api.mock.ts
index 8fafef6c5b..884c2865a4 100644
--- a/packages/shared/test/mocks/api.mock.ts
+++ b/packages/shared/test/mocks/api.mock.ts
@@ -62,6 +62,9 @@ const api: IApi = {
resolve()
})
},
+ bech32ToHex(address: string): string {
+ return ''
+ },
}
window['__WALLET__API__'] = api
diff --git a/yarn.lock b/yarn.lock
index 8f0389d853..dd54f573ea 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -343,10 +343,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@bloomwalletio/ui@0.18.8":
- version "0.18.8"
- resolved "https://npm.pkg.github.com/download/@bloomwalletio/ui/0.18.8/d9c6fed7e3dc5c52c2c5189b36ac465f09d3f859#d9c6fed7e3dc5c52c2c5189b36ac465f09d3f859"
- integrity sha512-uR75mYYm1dcH/QhMLoWYPl9oinxHglrN7fAh9agX6BGfQPP5lkiR0TAlaT/zC2pwB6RGY0qLgpL2FENnaZwmag==
+"@bloomwalletio/ui@0.18.11":
+ version "0.18.11"
+ resolved "https://npm.pkg.github.com/download/@bloomwalletio/ui/0.18.11/24c38a43cb9017ca5dfd3fcbe4aa4a75ecb7c731#24c38a43cb9017ca5dfd3fcbe4aa4a75ecb7c731"
+ integrity sha512-ojdsDZ27eLqNcXhTnz3ng/lrQ40XzFID4ml0nL7kIPdq0N7FNzsYa3R71FcXj2K9BUKM0u3AdKyhysvuEOOq/w==
dependencies:
"@floating-ui/dom" "1.4.3"
"@popperjs/core" "2.11.8"