diff --git a/bindings/nodejs/examples/how_tos/native_tokens/burn.ts b/bindings/nodejs/examples/how_tos/native_tokens/burn.ts index 51574417d8..f1e744ac5c 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/burn.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/burn.ts @@ -31,28 +31,24 @@ async function run() { let balance = await wallet.sync(); // Get a token with sufficient balance - const tokenId = balance.nativeTokens.find( - (t) => t.available >= MIN_AVAILABLE_AMOUNT, - )?.tokenId; - - let token = balance.nativeTokens.find( - (nativeToken) => - nativeToken.tokenId == tokenId && - Number(nativeToken.available) >= MIN_AVAILABLE_AMOUNT, + const tokenId = Object.keys(balance.nativeTokens).find( + (t) => balance.nativeTokens[t].available >= MIN_AVAILABLE_AMOUNT, ); - if (!token) { + + if (!tokenId) { throw new Error( - `Native token '${tokenId}' doesn't exist or there's not at least '${Number( + `No native token with at least '${Number( MIN_AVAILABLE_AMOUNT, )}' tokens of it in the wallet`, ); } + let token = balance.nativeTokens[tokenId]; console.log(`Balance before burning: ${token.available}`); // Burn a native token const transaction = await wallet - .prepareBurnNativeToken(token.tokenId, BURN_AMOUNT) + .prepareBurnNativeToken(tokenId, BURN_AMOUNT) .then((prepared) => prepared.send()); console.log(`Transaction sent: ${transaction.transactionId}`); @@ -68,9 +64,7 @@ async function run() { balance = await wallet.sync(); - token = balance.nativeTokens.find( - (nativeToken) => nativeToken.tokenId == tokenId, - ); + token = balance.nativeTokens[tokenId]; if (token) { console.log(`Balance after burning: ${token.available}`); } else { diff --git a/bindings/nodejs/examples/how_tos/native_tokens/melt.ts b/bindings/nodejs/examples/how_tos/native_tokens/melt.ts index bb39c32635..4282a65c61 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/melt.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/melt.ts @@ -33,9 +33,7 @@ async function run() { // Find first foundry and corresponding token id const tokenId = balance.foundries[0]; - let token = balance.nativeTokens.find( - (nativeToken) => nativeToken.tokenId == tokenId, - ); + let token = balance.nativeTokens[tokenId]; if (token == null) { throw new Error( `Couldn't find native token '${tokenId}' in the wallet`, @@ -45,10 +43,7 @@ async function run() { console.log(`Balance before melting: ${token.available}`); // Melt some of the circulating supply - const transaction = await wallet.meltNativeToken( - token.tokenId, - MELT_AMOUNT, - ); + const transaction = await wallet.meltNativeToken(tokenId, MELT_AMOUNT); console.log(`Transaction sent: ${transaction.transactionId}`); @@ -62,9 +57,7 @@ async function run() { ); balance = await wallet.sync(); - token = balance.nativeTokens.find( - (nativeToken) => nativeToken.tokenId == tokenId, - ); + token = balance.nativeTokens[tokenId]; if (token == null) { throw new Error( `Couldn't find native token '${tokenId}' in the wallet`, diff --git a/bindings/nodejs/examples/how_tos/native_tokens/mint.ts b/bindings/nodejs/examples/how_tos/native_tokens/mint.ts index 45ae306088..12a9707958 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/mint.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/mint.ts @@ -33,9 +33,7 @@ async function run() { // Find first foundry and corresponding token id const tokenId = balance.foundries[0]; - let token = balance.nativeTokens.find( - (nativeToken) => nativeToken.tokenId == tokenId, - ); + let token = balance.nativeTokens[tokenId]; if (token == null) { throw new Error( `Couldn't find native token '${tokenId}' in the wallet`, @@ -45,7 +43,7 @@ async function run() { // Mint some more native tokens const transaction = await wallet - .prepareMintNativeToken(token.tokenId, MINT_AMOUNT) + .prepareMintNativeToken(tokenId, MINT_AMOUNT) .then((prepared) => prepared.send()); console.log(`Transaction sent: ${transaction.transactionId}`); @@ -60,9 +58,7 @@ async function run() { ); balance = await wallet.sync(); - token = balance.nativeTokens.find( - (nativeToken) => nativeToken.tokenId == tokenId, - ); + token = balance.nativeTokens[tokenId]; if (token == null) { throw new Error( `Couldn't find native token '${tokenId}' in the wallet`, diff --git a/bindings/nodejs/examples/how_tos/native_tokens/send.ts b/bindings/nodejs/examples/how_tos/native_tokens/send.ts index 567949e077..4db1e73c2c 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/send.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/send.ts @@ -32,11 +32,13 @@ async function run() { let balance = await wallet.sync(); // Get a token with sufficient balance - const tokenId = balance.nativeTokens.find( - (t) => Number(t.available) >= Number(SEND_NATIVE_TOKEN_AMOUNT), - )?.tokenId; + const tokenId = Object.keys(balance.nativeTokens).find( + (t) => + Number(balance.nativeTokens[t].available) >= + Number(SEND_NATIVE_TOKEN_AMOUNT), + ); - if (tokenId != null) { + if (tokenId) { const outputs: SendNativeTokenParams[] = [ { address: RECV_ADDRESS, @@ -44,9 +46,7 @@ async function run() { }, ]; - let token = balance.nativeTokens.find( - (nativeToken) => nativeToken.tokenId == tokenId, - ); + let token = balance.nativeTokens[tokenId]; if (token == null) { throw new Error( `Couldn't find native token '${tokenId}' in the wallet`, @@ -68,9 +68,7 @@ async function run() { ); balance = await wallet.sync(); - token = balance.nativeTokens.find( - (nativeToken) => nativeToken.tokenId == tokenId, - ); + token = balance.nativeTokens[tokenId]; if (token == null) { throw new Error( `Couldn't find native token '${tokenId}' in the wallet`, diff --git a/bindings/nodejs/lib/types/block/output/index.ts b/bindings/nodejs/lib/types/block/output/index.ts index 3c03d98d44..2c5ab2a1a9 100644 --- a/bindings/nodejs/lib/types/block/output/index.ts +++ b/bindings/nodejs/lib/types/block/output/index.ts @@ -1,9 +1,10 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +export * from './block-issuer-key'; export * from './feature'; -export * from './unlock-condition'; -export * from './output'; -export * from './token-scheme'; export * from './irc-27'; export * from './irc-30'; +export * from './output'; +export * from './token-scheme'; +export * from './unlock-condition'; diff --git a/bindings/nodejs/lib/types/wallet/wallet.ts b/bindings/nodejs/lib/types/wallet/wallet.ts index db1cb5b450..83032273a2 100644 --- a/bindings/nodejs/lib/types/wallet/wallet.ts +++ b/bindings/nodejs/lib/types/wallet/wallet.ts @@ -1,11 +1,17 @@ // Copyright 2021-2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { AccountId, DelegationId, FoundryId, NftId } from '../block/id'; -import { HexEncodedString, u256, u64 } from '../utils'; +import { + AccountId, + DelegationId, + FoundryId, + NftId, + TokenId, +} from '../block/id'; +import { DecayedMana, u256, u64 } from '../utils'; import { IClientOptions } from '../client'; import { Bip44, SecretManagerType } from '../secret_manager/secret-manager'; -import { Bech32Address } from '../block'; +import { Bech32Address, OutputId } from '../block'; /** Options for the Wallet builder. */ export interface WalletOptions { @@ -25,25 +31,27 @@ export interface WalletOptions { /** A balance */ export interface Balance { - /** The balance of the base coin */ + /** Total and available amount of the base coin */ baseCoin: BaseCoinBalance; + /** Total and available mana */ + mana: ManaBalance; /** The required storage deposit for the outputs */ requiredStorageDeposit: RequiredStorageDeposit; /** The balance of the native tokens */ - nativeTokens: NativeTokenBalance[]; + nativeTokens: { [tokenId: TokenId]: NativeTokenBalance }; /** Account outputs */ - accounts: string[]; + accounts: AccountId[]; /** Foundry outputs */ - foundries: string[]; + foundries: FoundryId[]; /** Nft outputs */ - nfts: string[]; + nfts: NftId[]; /** Delegation outputs */ - delegations: string[]; + delegations: DelegationId[]; /** * Outputs with multiple unlock conditions and if they can currently be spent or not. If there is a * TimelockUnlockCondition or ExpirationUnlockCondition this can change at any time */ - potentiallyLockedOutputs: { [outputId: string]: boolean }; + potentiallyLockedOutputs: { [outputId: OutputId]: boolean }; } /** The balance of the base coin */ @@ -53,7 +61,15 @@ export interface BaseCoinBalance { /** The amount of the outputs that aren't used in a transaction */ available: u64; /** Voting power */ - votingPower: string; + votingPower: u64; +} + +/** Mana balances */ +export interface ManaBalance { + /** The total mana of the outputs */ + total: DecayedMana; + /** The mana of the outputs that isn't used in a transaction */ + available: DecayedMana; } /** The required storage deposit per output type */ @@ -72,8 +88,6 @@ export interface RequiredStorageDeposit { /** The balance of a native token */ export interface NativeTokenBalance { - /** The native token id. */ - tokenId: HexEncodedString; /** Some metadata of the native token. */ metadata?: string; /** The total native token balance. */ diff --git a/bindings/python/examples/how_tos/native_tokens/burn.py b/bindings/python/examples/how_tos/native_tokens/burn.py index 7ad18ceb4e..077cd3cb0c 100644 --- a/bindings/python/examples/how_tos/native_tokens/burn.py +++ b/bindings/python/examples/how_tos/native_tokens/burn.py @@ -17,17 +17,15 @@ wallet.set_stronghold_password(os.environ["STRONGHOLD_PASSWORD"]) # Find native token with enough balance -token = [ - native_balance for native_balance in balance.native_tokens if int( - native_balance.available, - 0) >= 10][0] -print(f'Balance before burning: {int(token.available, 0)}') +token_id, token = next( + (k, v) for k, v in balance.native_tokens.items() if v.available >= 10) +print(f'Balance before burning: {token.available}') burn_amount = 1 # Send transaction. transaction = wallet.prepare_burn_native_token( - token.token_id, burn_amount).send() + token_id, burn_amount).send() print(f'Transaction sent: {transaction.transaction_id}') # Wait for transaction to get included @@ -36,6 +34,5 @@ print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{block_id}') balance = wallet.sync() -available_balance = int( - [native_balance for native_balance in balance.native_tokens if native_balance.token_id == token.token_id][0].available, 0) +available_balance = balance.native_tokens[token_id].available print(f'Balance after burning: {available_balance}') diff --git a/bindings/python/examples/how_tos/native_tokens/melt.py b/bindings/python/examples/how_tos/native_tokens/melt.py index dd66fd965d..185910f2c6 100644 --- a/bindings/python/examples/how_tos/native_tokens/melt.py +++ b/bindings/python/examples/how_tos/native_tokens/melt.py @@ -16,8 +16,7 @@ # Find first foundry and corresponding token id token_id = balance.foundries[0] -available_balance = int( - [native_balance for native_balance in balance.native_tokens if native_balance.token_id == token_id][0].available, 0) +available_balance = balance.native_tokens[token_id].available print(f'Balance before melting: {available_balance}') if 'STRONGHOLD_PASSWORD' not in os.environ: @@ -37,6 +36,5 @@ print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{block_id}') balance = wallet.sync() -available_balance = int( - [native_balance for native_balance in balance.native_tokens if native_balance.token_id == token_id][0].available, 0) +available_balance = balance.native_tokens[token_id].available print(f'Balance after melting: {available_balance}') diff --git a/bindings/python/examples/how_tos/native_tokens/mint.py b/bindings/python/examples/how_tos/native_tokens/mint.py index 517eab633a..b3c69738bd 100644 --- a/bindings/python/examples/how_tos/native_tokens/mint.py +++ b/bindings/python/examples/how_tos/native_tokens/mint.py @@ -16,8 +16,7 @@ # Find first foundry and corresponding token id token_id = balance.foundries[0] -available_balance = int( - [native_balance for native_balance in balance.native_tokens if native_balance.token_id == token_id][0].available, 0) +available_balance = balance.native_tokens[token_id].available print(f'Balance before minting: {available_balance}') if 'STRONGHOLD_PASSWORD' not in os.environ: @@ -37,6 +36,5 @@ print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{block_id}') balance = wallet.sync() -available_balance = int( - [native_balance for native_balance in balance.native_tokens if native_balance.token_id == token_id][0].available, 0) +available_balance = balance.native_tokens[token_id].available print(f'Balance after minting: {available_balance}') diff --git a/bindings/python/examples/how_tos/native_tokens/send.py b/bindings/python/examples/how_tos/native_tokens/send.py index d960dd1191..dc334d1ce7 100644 --- a/bindings/python/examples/how_tos/native_tokens/send.py +++ b/bindings/python/examples/how_tos/native_tokens/send.py @@ -13,9 +13,9 @@ # Sync wallet with the node balance = wallet.sync() -token = [native_balance for native_balance in balance.native_tokens if int( - native_balance.available, 0) >= 10][0] -print(f'Balance before sending: {int(token.available, 0)}') +token_id, token = next( + (k, v) for k, v in balance.native_tokens.items() if v.available >= 10) +print(f'Balance before sending: {token.available}') if 'STRONGHOLD_PASSWORD' not in os.environ: raise Exception(".env STRONGHOLD_PASSWORD is undefined, see .env.example") @@ -25,7 +25,7 @@ outputs = [SendNativeTokenParams( "rms1qpszqzadsym6wpppd6z037dvlejmjuke7s24hm95s9fg9vpua7vluaw60xu", ( - token.token_id, + token_id, hex(10) ), )] @@ -39,6 +39,5 @@ print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{block_id}') balance = wallet.sync() -available_balance = int( - [native_balance for native_balance in balance.native_tokens if native_balance.token_id == token.token_id][0].available, 0) +available_balance = balance.native_tokens[token_id].available print(f'Balance after sending: {available_balance}') diff --git a/bindings/python/iota_sdk/types/balance.py b/bindings/python/iota_sdk/types/balance.py index c13f0f1466..8745faa35c 100644 --- a/bindings/python/iota_sdk/types/balance.py +++ b/bindings/python/iota_sdk/types/balance.py @@ -5,6 +5,7 @@ from typing import List, Optional from dataclasses import dataclass, field from dataclasses_json import config +from iota_sdk.types.decayed_mana import DecayedMana from iota_sdk.types.common import hex_str_decoder, HexStr, json @@ -16,6 +17,7 @@ class BaseCoinBalance: Attributes: total: The total balance. available: The available amount of the total balance. + voting_power: The voting power of the wallet. """ total: int = field(metadata=config( encoder=str @@ -23,6 +25,22 @@ class BaseCoinBalance: available: int = field(metadata=config( encoder=str )) + voting_power: int = field(metadata=config( + encoder=str + )) + + +@json +@dataclass +class ManaBalance: + """Mana fields for Balance. + + Attributes: + total: The total balance. + available: The available amount of the total balance. + """ + total: DecayedMana + available: DecayedMana @json @@ -65,7 +83,6 @@ class NativeTokensBalance: available: The available amount of the total native token balance. metadata: Some metadata of the native token. """ - token_id: HexStr total: int = field(metadata=config( encoder=hex, decoder=hex_str_decoder, @@ -84,6 +101,7 @@ class Balance: Attributes: base_coin: The base coin balance. + mana: Total and available mana. required_storage_deposit: The required storage deposit. native_tokens: The balances of all native tokens. accounts: All owned accounts. @@ -93,8 +111,9 @@ class Balance: potentially_locked_outputs: A list of potentially locked outputs. """ base_coin: BaseCoinBalance + mana: ManaBalance required_storage_deposit: RequiredStorageDeposit - native_tokens: List[NativeTokensBalance] + native_tokens: dict[HexStr, NativeTokensBalance] accounts: List[HexStr] foundries: List[HexStr] nfts: List[HexStr]