Skip to content

Commit

Permalink
Add StateMetadataFeature to bindings (#2030)
Browse files Browse the repository at this point in the history
* Add StateMetadataFeature to bindings, update MetadataFeature in JS, enable anchor state metadata validation

* Update doc comments
  • Loading branch information
Thoralf-M authored Feb 20, 2024
1 parent 28af551 commit cb65882
Show file tree
Hide file tree
Showing 15 changed files with 67 additions and 23 deletions.
4 changes: 3 additions & 1 deletion bindings/nodejs/examples/client/11-build-output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ async function run() {
const basicOutputWithMetadata = await client.buildBasicOutput({
amount: BigInt(1000000),
unlockConditions: [addressUnlockCondition],
features: [new MetadataFeature(utf8ToHex('Hello World!'))],
features: [
new MetadataFeature({ data: utf8ToHex('Hello World!') }),
],
});

console.log(JSON.stringify(basicOutputWithMetadata, null, 2));
Expand Down
4 changes: 2 additions & 2 deletions bindings/nodejs/examples/client/13-build-account-output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ async function run() {
],
features: [
new SenderFeature(new Ed25519Address(hexAddress)),
new MetadataFeature(utf8ToHex('hello')),
new MetadataFeature({ data: utf8ToHex('hello') }),
],
immutableFeatures: [
new IssuerFeature(new Ed25519Address(hexAddress)),
new MetadataFeature(utf8ToHex('hello')),
new MetadataFeature({ data: utf8ToHex('hello') }),
],
});

Expand Down
4 changes: 3 additions & 1 deletion bindings/nodejs/examples/client/15-build-nft-output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ async function run() {
],
features: [
new SenderFeature(new Ed25519Address(hexAddress)),
new MetadataFeature(utf8ToHex('mutable metadata')),
new MetadataFeature({
data: utf8ToHex('mutable metadata'),
}),
new TagFeature(utf8ToHex('my tag')),
],
});
Expand Down
6 changes: 4 additions & 2 deletions bindings/nodejs/examples/how_tos/outputs/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,17 @@ async function run() {
const nftOutputWithMetadata = await client.buildNftOutput({
nftId: '0x0000000000000000000000000000000000000000000000000000000000000000',
unlockConditions: [addressUnlockCondition],
features: [new MetadataFeature(utf8ToHex('Hello, World!'))],
features: [
new MetadataFeature({ data: utf8ToHex('Hello, World!') }),
],
});

// Output with immutable metadata feature
const nftOutputWithImmutableMetadata = await client.buildNftOutput({
nftId: '0x0000000000000000000000000000000000000000000000000000000000000000',
unlockConditions: [addressUnlockCondition],
immutableFeatures: [
new MetadataFeature(utf8ToHex('Hello, World!')),
new MetadataFeature({ data: utf8ToHex('Hello, World!') }),
],
});

Expand Down
31 changes: 27 additions & 4 deletions bindings/nodejs/lib/types/block/output/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import { EpochIndex } from '../../block/slot';
import { NativeToken } from '../../models/native-token';
import { HexEncodedString } from '../../utils/hex-encoding';

/**
* Printable ASCII characters.
*/
export declare type PrintableASCII = string;

/**
* All of the feature block types.
*/
Expand Down Expand Up @@ -88,14 +93,30 @@ class IssuerFeature extends Feature {
*/
class MetadataFeature extends Feature {
/** Defines metadata (arbitrary binary data) that will be stored in the output. */
readonly data: string;
readonly entries: { [key: PrintableASCII]: HexEncodedString };

/**
* @param data The metadata stored with the feature.
* @param entries The metadata stored with the feature.
*/
constructor(data: string) {
constructor(entries: { [key: PrintableASCII]: HexEncodedString }) {
super(FeatureType.Metadata);
this.data = data;
this.entries = entries;
}
}

/**
* A Metadata Feature that can only be changed by the State Controller.
*/
class StateMetadataFeature extends Feature {
/** Defines metadata (arbitrary binary data) that will be stored in the output. */
readonly entries: { [key: PrintableASCII]: HexEncodedString };

/**
* @param entries The metadata stored with the feature.
*/
constructor(entries: { [key: PrintableASCII]: HexEncodedString }) {
super(FeatureType.StateMetadata);
this.entries = entries;
}
}

Expand Down Expand Up @@ -213,6 +234,7 @@ const FeatureDiscriminator = {
{ value: SenderFeature, name: FeatureType.Sender as any },
{ value: IssuerFeature, name: FeatureType.Issuer as any },
{ value: MetadataFeature, name: FeatureType.Metadata as any },
{ value: StateMetadataFeature, name: FeatureType.StateMetadata as any },
{ value: TagFeature, name: FeatureType.Tag as any },
{ value: NativeTokenFeature, name: FeatureType.NativeToken as any },
{ value: BlockIssuerFeature, name: FeatureType.BlockIssuer as any },
Expand All @@ -227,6 +249,7 @@ export {
SenderFeature,
IssuerFeature,
MetadataFeature,
StateMetadataFeature,
TagFeature,
NativeTokenFeature,
BlockIssuerFeature,
Expand Down
2 changes: 1 addition & 1 deletion bindings/nodejs/lib/types/block/output/irc-27.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class Irc27Metadata {
}

asFeature(): MetadataFeature {
return new MetadataFeature(this.asHex());
return new MetadataFeature({ 'irc-27': this.asHex() });
}
}

Expand Down
2 changes: 1 addition & 1 deletion bindings/nodejs/lib/types/block/output/irc-30.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class Irc30Metadata {
}

asFeature(): MetadataFeature {
return new MetadataFeature(this.asHex());
return new MetadataFeature({ 'irc-30': this.asHex() });
}
}

Expand Down
4 changes: 2 additions & 2 deletions bindings/python/examples/client/build_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
]
features = [
SenderFeature(Ed25519Address(hexAddress)),
MetadataFeature(utf8_to_hex('Hello, World!'))
MetadataFeature({'data': utf8_to_hex('Hello, World!')})
]
immutable_features = [
IssuerFeature(Ed25519Address(hexAddress)),
MetadataFeature(utf8_to_hex('Hello, World!'))
MetadataFeature({'data': utf8_to_hex('Hello, World!')})
]

# Build account output
Expand Down
2 changes: 1 addition & 1 deletion bindings/python/examples/client/build_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
address_unlock_condition,
],
features=[
MetadataFeature(utf8_to_hex('Hello, World!'))
MetadataFeature({'data': utf8_to_hex('Hello, World!')})
],
amount=1000000,
)
Expand Down
4 changes: 2 additions & 2 deletions bindings/python/examples/how_tos/outputs/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
address_unlock_condition,
],
features=[
MetadataFeature(utf8_to_hex('Hello, World!'))
MetadataFeature({'data': utf8_to_hex('Hello, World!')})
],
)
outputs.append(nft_output)
Expand All @@ -69,7 +69,7 @@
address_unlock_condition,
],
immutable_features=[
MetadataFeature(utf8_to_hex('Hello, World!'))
MetadataFeature({'data': utf8_to_hex('Hello, World!')})
],
)
outputs.append(nft_output)
Expand Down
18 changes: 17 additions & 1 deletion bindings/python/iota_sdk/types/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,20 @@ class MetadataFeature:
entries: Dict[str, HexStr]


@json
@dataclass
class StateMetadataFeature:
"""A Metadata Feature that can only be changed by the State Controller.
Attributes:
entries: A key-value map where the keys are graphic ASCII strings and the values hex-encoded binary data.
"""
type: int = field(
default_factory=lambda: int(
FeatureType.StateMetadata),
init=False)
entries: Dict[str, HexStr]


@json
@dataclass
class TagFeature:
Expand Down Expand Up @@ -149,7 +163,7 @@ class StakingFeature:


Feature: TypeAlias = Union[SenderFeature, IssuerFeature,
MetadataFeature, TagFeature, NativeTokenFeature, BlockIssuerFeature, StakingFeature]
MetadataFeature, StateMetadataFeature, TagFeature, NativeTokenFeature, BlockIssuerFeature, StakingFeature]


# pylint: disable=too-many-return-statements
Expand All @@ -167,6 +181,8 @@ def deserialize_feature(d: Dict[str, Any]) -> Feature:
return IssuerFeature.from_dict(d)
if feature_type == FeatureType.Metadata:
return MetadataFeature.from_dict(d)
if feature_type == FeatureType.StateMetadata:
return StateMetadataFeature.from_dict(d)
if feature_type == FeatureType.Tag:
return TagFeature.from_dict(d)
if feature_type == FeatureType.NativeToken:
Expand Down
2 changes: 1 addition & 1 deletion bindings/python/iota_sdk/types/irc_27.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ def as_hex(self):
def as_feature(self):
"""Turns this schema into a MetadataFeature type
"""
MetadataFeature(self.as_hex())
MetadataFeature({'irc-27': self.as_hex()})
2 changes: 1 addition & 1 deletion bindings/python/iota_sdk/types/irc_30.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ def as_hex(self):
def as_feature(self):
"""Turns this schema into a MetadataFeature type
"""
MetadataFeature(self.as_hex())
MetadataFeature({'irc-30': self.as_hex()})
3 changes: 1 addition & 2 deletions sdk/src/types/block/output/anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,7 @@ impl AnchorOutput {
} else if next_state.state_index == current_state.state_index {
// Governance transition.
if current_state.amount != next_state.amount
// TODO https://github.com/iotaledger/iota-sdk/issues/1650
// || current_state.state_metadata != next_state.state_metadata
|| current_state.features().state_metadata() != next_state.features().state_metadata()
{
return Err(TransactionFailureReason::AnchorInvalidGovernanceTransition);
}
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/types/block/output/feature/state_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use super::{
};
use crate::types::block::{output::StorageScore, protocol::WorkScore, Error};

/// Defines metadata, arbitrary binary data, that will be stored in the output.
/// A Metadata Feature that can only be changed by the State Controller.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct StateMetadataFeature(pub(crate) MetadataBTreeMapPrefix);

Expand Down

0 comments on commit cb65882

Please sign in to comment.