Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Improve Address conversions #1194

Merged
merged 8 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion .github/workflows/nova-build-temp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
TARGET_COMMIT:
description: "Target Commit Hash for the SDK"
required: false
default: "aa1b1de58731dbbf9dd0f5e2960fd11b0056b633"
default: "772a5665afb7663b5ddb2c1e4780d03401fc7aa2"
environment:
type: choice
description: "Select the environment to deploy to"
Expand Down
1 change: 0 additions & 1 deletion api/src/models/api/nova/IAddressDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ export interface IAddressDetails {
hex?: string;
type?: AddressType;
label?: string;
capabilities?: number[];
}
34 changes: 22 additions & 12 deletions api/src/utils/nova/addressHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ImplicitAccountCreationAddress,
} from "@iota/sdk-nova";
import { plainToInstance } from "class-transformer";
import logger from "../../logger";
import { IAddressDetails } from "../../models/api/nova/IAddressDetails";
import { HexHelper } from "../hexHelper";

Expand All @@ -31,6 +32,7 @@ export class AddressHelper {
let bech32: string;
let hex: string;
let type: AddressType;

if (Utils.isAddressValid(addressString)) {
try {
const address: Address = Utils.parseBech32Address(addressString);
Expand All @@ -41,27 +43,28 @@ export class AddressHelper {
hex = Utils.bech32ToHex(addressString);
}
} catch (e) {
console.error(e);
logger.debug(`Failed parsing Address. Cause: ${e}`);
}
}

if (!bech32) {
// We assume this is hex
hex = addressString;

if (typeHint) {
bech32 = this.computeBech32FromHexAndType(hex, type, hrp);
bech32 = this.computeBech32FromHexAndType(hex, typeHint, hrp);
}
}

return {
bech32,
hex: hex ? HexHelper.addPrefix(hex) : hex,
type,
type: type ?? typeHint,
label: AddressHelper.typeLabel(type),
};
}

private static buildAddressFromTypes(address: Address, hrp: string, capabilities?: number[]): IAddressDetails {
private static buildAddressFromTypes(address: Address, hrp: string): IAddressDetails {
let hex: string = "";
let bech32: string = "";

Expand All @@ -79,31 +82,34 @@ export class AddressHelper {
hex = innerAddress.pubKeyHash;
}

bech32 = this.computeBech32FromHexAndType(hex, address.type, hrp);
bech32 = Utils.addressToBech32(address, hrp);

return {
bech32,
hex,
type: address.type,
label: AddressHelper.typeLabel(address.type),
capabilities,
};
}

private static computeBech32FromHexAndType(hex: string, addressType: AddressType, hrp: string) {
let bech32 = "";
let address: Address | null = null;

if (addressType === AddressType.Ed25519) {
bech32 = Utils.hexToBech32(hex, hrp);
address = new Ed25519Address(hex);
} else if (addressType === AddressType.Account) {
bech32 = Utils.accountIdToBech32(hex, hrp);
address = new AccountAddress(hex);
} else if (addressType === AddressType.Nft) {
bech32 = Utils.nftIdToBech32(hex, hrp);
address = new NftAddress(hex);
} else if (addressType === AddressType.Anchor) {
// Update to Utils.anchorIdToBech32 when it gets implemented
bech32 = Utils.accountIdToBech32(hex, hrp);
address = new AnchorAddress(hex);
} else if (addressType === AddressType.ImplicitAccountCreation) {
bech32 = Utils.hexToBech32(hex, hrp);
address = new ImplicitAccountCreationAddress(hex);
}

if (address !== null) {
bech32 = Utils.addressToBech32(address, hrp);
}

return bech32;
Expand All @@ -123,6 +129,10 @@ export class AddressHelper {
return "NFT";
} else if (addressType === AddressType.Anchor) {
return "Anchor";
} else if (addressType === AddressType.ImplicitAccountCreation) {
return "Implicit Account Creation";
}

return "Unknown";
}
}
12 changes: 8 additions & 4 deletions client/src/app/components/nova/OutputView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
SimpleTokenScheme,
DelegationOutput,
Utils,
AccountAddress,
NftAddress,
} from "@iota/sdk-wasm-nova/web";
import UnlockConditionView from "./UnlockConditionView";
import CopyButton from "../CopyButton";
Expand Down Expand Up @@ -40,7 +42,7 @@ const OutputView: React.FC<OutputViewProps> = ({ outputId, output, showCopyAmoun
const [isFormattedBalance, setIsFormattedBalance] = useState(true);
const { bech32Hrp, name: network } = useNetworkInfoNova((s) => s.networkInfo);

const aliasOrNftBech32 = buildAddressForAliasOrNft(outputId, output, bech32Hrp);
const aliasOrNftBech32 = buildAddressForAccountOrNft(outputId, output, bech32Hrp);
const outputIdTransactionPart = `${outputId.slice(0, 8)}....${outputId.slice(-8, -4)}`;
const outputIdIndexPart = outputId.slice(-4);
const manaEntries = getManaKeyValueEntries(manaDetails);
Expand Down Expand Up @@ -215,19 +217,21 @@ const OutputView: React.FC<OutputViewProps> = ({ outputId, output, showCopyAmoun
);
};

function buildAddressForAliasOrNft(outputId: string, output: Output, bech32Hrp: string): string {
function buildAddressForAccountOrNft(outputId: string, output: Output, bech32Hrp: string): string {
let bech32: string = "";

if (output.type === OutputType.Account) {
const accountIdFromOutput = (output as AccountOutput).accountId;
const accountId = HexHelper.toBigInt256(accountIdFromOutput).eq(bigInt.zero)
? Utils.computeAccountId(outputId)
: accountIdFromOutput;
bech32 = Utils.accountIdToBech32(accountId, bech32Hrp);
const accountAddress = new AccountAddress(accountId);
bech32 = Utils.addressToBech32(accountAddress, bech32Hrp);
} else if (output.type === OutputType.Nft) {
const nftIdFromOutput = (output as NftOutput).nftId;
const nftId = HexHelper.toBigInt256(nftIdFromOutput).eq(bigInt.zero) ? Utils.computeNftId(outputId) : nftIdFromOutput;
bech32 = Utils.nftIdToBech32(nftId, bech32Hrp);
const nftAddress = new NftAddress(nftId);
bech32 = Utils.addressToBech32(nftAddress, bech32Hrp);
}

return bech32;
Expand Down
9 changes: 5 additions & 4 deletions client/src/app/components/nova/address/section/nft/Nft.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { tryParseMetadata } from "~helpers/stardust/metadataUtils";
import { INftImmutableMetadata } from "~models/api/stardust/nft/INftImmutableMetadata";
import "./Nft.scss";
import { useNetworkInfoNova } from "~/helpers/nova/networkInfo";
import { MetadataFeature, NftOutput, Utils } from "@iota/sdk-wasm-nova/web";
import { MetadataFeature, NftAddress, NftOutput, Utils } from "@iota/sdk-wasm-nova/web";
import TruncatedId from "~/app/components/stardust/TruncatedId";
import { TransactionsHelper } from "~/helpers/nova/transactionsHelper";

Expand All @@ -32,7 +32,8 @@ const Nft: React.FC<NftProps> = ({ nftOutput }) => {
const [metadata, setMetadata] = useState<MetadataFeature | null>(null);
const [issuerId, setIssuerId] = useState<string | null>(null);
const [standardMetadata, setStandardMetadata] = useState<INftImmutableMetadata | null>();
const nftAddress = Utils.hexToBech32(nftOutput.nftId, bech32Hrp);
const nftAddress = new NftAddress(nftOutput.nftId);
const nftBech32Address = Utils.addressToBech32(nftAddress, bech32Hrp);
const [isWhitelisted] = useTokenRegistryNftCheck(issuerId, nftOutput.nftId);
const [name, setName] = useState<string | null>();
const [uri, isNftUriLoading] = useNftMetadataUri(standardMetadata?.uri);
Expand Down Expand Up @@ -75,9 +76,9 @@ const Nft: React.FC<NftProps> = ({ nftOutput }) => {
return (
<div className="nft-card">
<div className="nft-card__metadata">
<Link to={`/${network}/addr/${nftAddress}`}>{nftImageContent}</Link>
<Link to={`/${network}/addr/${nftBech32Address}`}>{nftImageContent}</Link>
<span className="nft-card__id">
<TruncatedId id={nftOutput.nftId} link={`/${network}/addr/${nftAddress}`} />
<TruncatedId id={nftOutput.nftId} link={`/${network}/addr/${nftBech32Address}`} />
</span>
</div>
{name && isWhitelisted && <span className="nft-card__name truncate">{name}</span>}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { TRANSACTION_FAILURE_REASON_STRINGS, Transaction, TransactionMetadata, TransactionState, Utils } from "@iota/sdk-wasm-nova/web";
import {
TRANSACTION_FAILURE_REASON_STRINGS,
Transaction,
TransactionMetadata,
TransactionState,
Utils,
AccountAddress,
} from "@iota/sdk-wasm-nova/web";
import React from "react";
import Spinner from "../../../Spinner";
import TruncatedId from "~/app/components/stardust/TruncatedId";
Expand Down Expand Up @@ -63,15 +70,20 @@ const TransactionMetadataSection: React.FC<TransactionMetadataSectionProps> = ({
{transaction?.allotments && (
<div className="section--data">
<div className="label">Mana Allotment Accounts</div>
{transaction?.allotments?.map((allotment, idx) => (
<div className="value code highlight margin-b-t" key={idx}>
<TruncatedId
id={allotment.accountId}
link={`/${network}/addr/${Utils.accountIdToBech32(allotment.accountId, bech32Hrp)}`}
showCopyButton
/>
</div>
))}
{transaction?.allotments?.map((allotment, idx) => {
const accountAddress = new AccountAddress(allotment.accountId);
const accountBech32 = Utils.addressToBech32(accountAddress, bech32Hrp);

return (
<div className="value code highlight margin-b-t" key={idx}>
<TruncatedId
id={allotment.accountId}
link={`/${network}/addr/${accountBech32}`}
showCopyButton
/>
</div>
);
})}
</div>
)}
</>
Expand Down
4 changes: 2 additions & 2 deletions client/src/app/routes/nova/TransactionPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable react/jsx-no-useless-fragment */
import { BasicBlockBody, SignedTransactionPayload, Utils } from "@iota/sdk-wasm-nova/web";
import { AccountAddress, BasicBlockBody, SignedTransactionPayload, Utils } from "@iota/sdk-wasm-nova/web";
import React, { useEffect, useState } from "react";
import { RouteComponentProps } from "react-router-dom";
import metadataInfoMessage from "~assets/modals/stardust/block/metadata.json";
Expand Down Expand Up @@ -135,7 +135,7 @@ const TransactionPage: React.FC<RouteComponentProps<TransactionPageProps>> = ({
<div className="value code highlight">
<TruncatedId
id={block.header.issuerId}
link={`/${network}/addr/${Utils.accountIdToBech32(block.header.issuerId, bech32Hrp)}`}
link={`/${network}/addr/${Utils.addressToBech32(new AccountAddress(block.header.issuerId), bech32Hrp)}`}
showCopyButton={true}
/>
</div>
Expand Down
31 changes: 18 additions & 13 deletions client/src/helpers/nova/addressHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class AddressHelper {
}

if (!bech32) {
// We assume this is hex and either use the hint or assume ed25519
// We assume this is hex
hex = addressString;
type = typeHint ?? AddressType.Ed25519;
bech32 = this.computeBech32FromHexAndType(hex, type, hrp);
Expand All @@ -51,12 +51,12 @@ export class AddressHelper {
return {
bech32,
hex: hex ? HexHelper.addPrefix(hex) : hex,
type,
type: type ?? typeHint,
label: AddressHelper.typeLabel(type),
};
}

private static buildAddressFromTypes(address: Address, hrp: string, capabilities?: number[]): IAddressDetails {
private static buildAddressFromTypes(address: Address, hrp: string): IAddressDetails {
let hex: string = "";
let bech32: string = "";

Expand All @@ -74,31 +74,34 @@ export class AddressHelper {
hex = (innerAddress as Ed25519Address).pubKeyHash;
}

bech32 = this.computeBech32FromHexAndType(hex, address.type, hrp);
bech32 = Utils.addressToBech32(address, hrp);

return {
bech32,
hex,
type: address.type,
label: AddressHelper.typeLabel(address.type),
capabilities,
};
}

private static computeBech32FromHexAndType(hex: string, addressType: AddressType, hrp: string) {
let bech32 = "";
let address: Address | null = null;

if (addressType === AddressType.Ed25519) {
bech32 = Utils.hexToBech32(hex, hrp);
address = new Ed25519Address(hex);
} else if (addressType === AddressType.Account) {
bech32 = Utils.accountIdToBech32(hex, hrp);
address = new AccountAddress(hex);
} else if (addressType === AddressType.Nft) {
bech32 = Utils.nftIdToBech32(hex, hrp);
address = new NftAddress(hex);
} else if (addressType === AddressType.Anchor) {
// TODO Utils.anchorIdToBech32 does not exist https://github.com/iotaledger/iota-sdk/issues/1973
bech32 = Utils.accountIdToBech32(hex, hrp);
address = new AnchorAddress(hex);
} else if (addressType === AddressType.ImplicitAccountCreation) {
bech32 = Utils.hexToBech32(hex, hrp);
address = new ImplicitAccountCreationAddress(hex);
}

if (address !== null) {
bech32 = Utils.addressToBech32(address, hrp);
}

return bech32;
Expand All @@ -109,7 +112,7 @@ export class AddressHelper {
* @param addressType The address type to get the label for.
* @returns The label.
*/
private static typeLabel(addressType?: number): string | undefined {
private static typeLabel(addressType?: AddressType): string | undefined {
if (addressType === AddressType.Ed25519) {
return "Ed25519";
} else if (addressType === AddressType.Account) {
Expand All @@ -119,7 +122,9 @@ export class AddressHelper {
} else if (addressType === AddressType.Anchor) {
return "Anchor";
} else if (addressType === AddressType.ImplicitAccountCreation) {
return "Implicit";
return "Implicit Account Creation";
}

return "Unknown";
}
}
1 change: 0 additions & 1 deletion client/src/models/api/nova/IAddressDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ export interface IAddressDetails {
hex?: string;
type?: AddressType;
label?: string;
capabilities?: number[];
}
2 changes: 1 addition & 1 deletion setup_nova.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
SDK_DIR="iota-sdk"
TARGET_COMMIT="aa1b1de58731dbbf9dd0f5e2960fd11b0056b633"
TARGET_COMMIT="772a5665afb7663b5ddb2c1e4780d03401fc7aa2"

if [ ! -d "$SDK_DIR" ]; then
git clone -b 2.0 [email protected]:iotaledger/iota-sdk.git
Expand Down
Loading