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

Nodejs: Anchor related changes #1528

Merged
merged 4 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion bindings/nodejs/lib/types/block/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { plainToInstance, Type } from 'class-transformer';
import { HexEncodedString } from '../utils';
import { AccountId, NftId } from './id';
import { AccountId, AnchorId, NftId } from './id';

/**
* An address prepended by its network type.
Expand All @@ -22,6 +22,8 @@ enum AddressType {
Nft = 16,
/** An implicit account creation address. */
ImplicitAccountCreation = 24,
/** An Anchor address. */
Anchor = 28,
/** An address with restricted capabilities. */
Restricted = 40,
}
Expand Down Expand Up @@ -65,6 +67,8 @@ abstract class Address {
ImplicitAccountCreationAddress,
data,
) as any as ImplicitAccountCreationAddress;
} else if (data.type == AddressType.Anchor) {
return plainToInstance(AnchorAddress, data) as any as AnchorAddress;
} else if (data.type == AddressType.Restricted) {
return plainToInstance(
RestrictedAddress,
Expand Down Expand Up @@ -160,6 +164,27 @@ class ImplicitAccountCreationAddress extends Address {
}
}

/**
* An Anchor address.
*/
class AnchorAddress extends Address {
/**
* The anchor ID.
*/
readonly anchorId: AnchorId;
/**
* @param address An anchor address as anchor ID.
*/
constructor(address: AnchorId) {
super(AddressType.Anchor);
this.anchorId = address;
}

toString(): string {
return this.anchorId;
}
}

const RestrictedAddressDiscriminator = {
property: 'type',
subTypes: [
Expand Down Expand Up @@ -234,6 +259,7 @@ const AddressDiscriminator = {
value: ImplicitAccountCreationAddress,
name: AddressType.ImplicitAccountCreation as any,
},
{ value: AnchorAddress, name: AddressType.Anchor as any },
{ value: RestrictedAddress, name: AddressType.Restricted as any },
],
};
Expand All @@ -246,4 +272,5 @@ export {
Ed25519Address,
AccountAddress,
NftAddress,
AnchorAddress,
};
5 changes: 5 additions & 0 deletions bindings/nodejs/lib/types/block/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import { HexEncodedString } from '../utils';
*/
export type AccountId = HexEncodedString;

/**
* An Anchor ID represented as hex-encoded string.
*/
export type AnchorId = HexEncodedString;

/**
* An NFT ID represented as hex-encoded string.
*/
Expand Down
67 changes: 62 additions & 5 deletions bindings/nodejs/lib/types/block/output/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { plainToInstance, Type } from 'class-transformer';
import { HexEncodedString, hexToBigInt, NumericString, u64 } from '../../utils';
import { TokenScheme, TokenSchemeDiscriminator } from './token-scheme';
import { INativeToken } from '../../models';
import { AccountId, DelegationId } from '../id';
import { AccountId, NftId, AnchorId, DelegationId } from '../id';
import { EpochIndex } from '../../block/slot';

export type OutputId = HexEncodedString;
Expand All @@ -31,6 +31,8 @@ enum OutputType {
Nft = 3,
/** A Delegation output. */
Delegation = 4,
/** An Anchor output. */
Anchor = 5,
}

/**
Expand Down Expand Up @@ -76,6 +78,13 @@ abstract class Output {
return plainToInstance(FoundryOutput, data) as any as FoundryOutput;
} else if (data.type == OutputType.Nft) {
return plainToInstance(NftOutput, data) as any as NftOutput;
} else if (data.type == OutputType.Delegation) {
return plainToInstance(
DelegationOutput,
data,
) as any as DelegationOutput;
} else if (data.type == OutputType.Anchor) {
return plainToInstance(AnchorOutput, data) as any as AnchorOutput;
}
throw new Error('Invalid JSON');
}
Expand Down Expand Up @@ -185,7 +194,7 @@ class AccountOutput extends ImmutableFeaturesOutput {
* Unique identifier of the account, which is the BLAKE2b-256 hash of the Output ID that created it.
* Unless its a newly created account, then the id is zeroed.
*/
readonly accountId: HexEncodedString;
readonly accountId: AccountId;
/**
* A counter that denotes the number of foundries created by this account output.
*/
Expand All @@ -205,7 +214,7 @@ class AccountOutput extends ImmutableFeaturesOutput {
constructor(
amount: u64,
mana: u64,
accountId: HexEncodedString,
accountId: AccountId,
foundryCounter: number,
unlockConditions: UnlockCondition[],
) {
Expand All @@ -215,6 +224,53 @@ class AccountOutput extends ImmutableFeaturesOutput {
this.mana = mana;
}
}

/**
* An Anchor output.
*/
class AnchorOutput extends ImmutableFeaturesOutput {
/**
* Unique identifier of the anchor, which is the BLAKE2b-256 hash of the Output ID that created it.
* Unless its a newly created anchor, then the id is zeroed.
*/
readonly anchorId: AnchorId;
/**
* A counter that must increase by 1 every time the anchor output is state transitioned.
*/
readonly stateIndex: number;
/**
* The amount of (stored) Mana held by the output.
*/
readonly mana: u64;
/**
* Metadata that can only be changed by the state controller.
*/
readonly stateMetadata?: HexEncodedString;

/**
* @param amount The amount of the output.
* @param mana The amount of stored mana.
* @param anchorId The anchor ID as hex-encoded string.
* @param stateIndex A counter that must increase by 1 every time the anchor output is state transitioned.
* @param unlockConditions The unlock conditions of the output.
* @param stateMetadata Metadata that can only be changed by the state controller.
*/
constructor(
amount: u64,
mana: u64,
anchorId: AnchorId,
stateIndex: number,
unlockConditions: UnlockCondition[],
stateMetadata?: HexEncodedString,
) {
super(OutputType.Account, amount, unlockConditions);
this.anchorId = anchorId;
this.stateIndex = stateIndex;
this.mana = mana;
this.stateMetadata = stateMetadata;
}
}

/**
* An NFT output.
*/
Expand All @@ -223,7 +279,7 @@ class NftOutput extends ImmutableFeaturesOutput {
* Unique identifier of the NFT, which is the BLAKE2b-256 hash of the Output ID that created it.
* Unless its newly minted, then the id is zeroed.
*/
readonly nftId: HexEncodedString;
readonly nftId: NftId;

/**
* The amount of (stored) Mana held by the output.
Expand All @@ -239,7 +295,7 @@ class NftOutput extends ImmutableFeaturesOutput {
constructor(
amount: u64,
mana: u64,
nftId: HexEncodedString,
nftId: NftId,
unlockConditions: UnlockCondition[],
) {
super(OutputType.Nft, amount, unlockConditions);
Expand Down Expand Up @@ -359,6 +415,7 @@ export {
CommonOutput,
BasicOutput,
AccountOutput,
AnchorOutput,
NftOutput,
FoundryOutput,
DelegationOutput,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ enum UnlockType {
* An NFT unlock.
*/
Nft = 3,
/**
* An Anchor unlock.
*/
Anchor = 4,
}

/**
Expand Down Expand Up @@ -117,6 +121,24 @@ class NftUnlock extends Unlock {
}
}

/**
* An unlock which must reference a previous unlock which unlocks the anchor that the input is locked to.
*/
class AnchorUnlock extends Unlock {
/**
* The reference.
*/
readonly reference: number;

/**
* @param reference An index referencing a previous unlock.
*/
constructor(reference: number) {
super(UnlockType.Anchor);
this.reference = reference;
}
}

const UnlockDiscriminator = {
property: 'type',
subTypes: [
Expand All @@ -136,6 +158,10 @@ const UnlockDiscriminator = {
value: NftUnlock,
name: UnlockType.Nft as any,
},
{
value: AnchorUnlock,
name: UnlockType.Anchor as any,
},
],
};

Expand All @@ -146,5 +172,6 @@ export {
ReferenceUnlock,
AccountUnlock,
NftUnlock,
AnchorUnlock,
UnlockDiscriminator,
};