Add custom data to a mosaic.
Metadata is a Symbol feature that can be used to attach information about mosaics. For example, small pieces of data such as legal name, ticker, or ISIN, can be assigned as on-chain metadata, while sizable documents, like the prospectus or investor agreement, can be kept off-chain.
In this tutorial, you are going to implement a program to add relevant data to a mosaic.
Imagine that the company ComfyClothingCompany has applied for an ISIN code to conduct an STO.
After receiving the code US0000000000
, the company decided to represent the company shares creating a mosaic named cc.shares
.
Before distributing the shares between the investors, ComfyClothingCompany wants to attach its ISIN code and legal name to the shares definition.
symbol.xym
to pay for transaction fees, create mosaics and register namespaces.cc.shares
, define two MosaicMetatadaTransaction
to add the ISIN and legal name to the mosaic:ISIN
, Value: US00000000
.// replace with network type
const networkType = NetworkType.TEST_NET;
// replace with company private key
const companyPrivateKey = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
const companyAccount = Account.createFromPrivateKey(companyPrivateKey, networkType);
// replace with mosaic id
const mosaicId = new NamespaceId('cc.shares');
const isin = 'US00000000';
const isinMetadataTransaction = MosaicMetadataTransaction.create(
Deadline.create(),
companyAccount.address,
KeyGenerator.generateUInt64Key('ISIN'),
mosaicId,
isin.length,
isin,
networkType,
);
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with company private key
const companyPrivateKey = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
const companyAccount = symbol_sdk_1.Account.createFromPrivateKey(companyPrivateKey, networkType);
// replace with mosaic id
const mosaicId = new symbol_sdk_1.NamespaceId('cc.shares');
const isin = 'US00000000';
const isinMetadataTransaction = symbol_sdk_1.MosaicMetadataTransaction.create(symbol_sdk_1.Deadline.create(), companyAccount.address, symbol_sdk_1.KeyGenerator.generateUInt64Key('ISIN'), mosaicId, isin.length, isin, networkType);
NAME
, Value: ComfyClothingCompany
.const name = 'ComfyClothingCompany';
const nameMetadataTransaction = MosaicMetadataTransaction.create(
Deadline.create(),
companyAccount.address,
KeyGenerator.generateUInt64Key('NAME'),
mosaicId,
name.length,
name,
networkType,
);
const name = 'ComfyClothingCompany';
const nameMetadataTransaction = symbol_sdk_1.MosaicMetadataTransaction.create(symbol_sdk_1.Deadline.create(), companyAccount.address, symbol_sdk_1.KeyGenerator.generateUInt64Key('NAME'), mosaicId, name.length, name, networkType);
2. All metadata is attached only with the consent of the mosaic creator through Aggregate Transactions. Wrap the metadata transactions inside an AggregateCompleteTransaction and sign the aggregate with the company’s account.
const aggregateTransaction = AggregateTransaction.createComplete(
Deadline.create(),
[isinMetadataTransaction.toAggregate(companyAccount.publicAccount),
nameMetadataTransaction.toAggregate(companyAccount.publicAccount)],
networkType,
[],
UInt64.fromUint(2000000));
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createComplete(symbol_sdk_1.Deadline.create(), [isinMetadataTransaction.toAggregate(companyAccount.publicAccount),
nameMetadataTransaction.toAggregate(companyAccount.publicAccount)], networkType, [], symbol_sdk_1.UInt64.fromUint(2000000));
Note
In this example, the account signing the transaction is the creator of the mosaic. For that reason, the aggregate can be defined as complete. If a different account owned the mosaic, you would set the aggregate as bonded, and the mosaic creator would opt-in the metadata request by cosigning the transaction.
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash = '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = companyAccount.sign(aggregateTransaction, networkGenerationHash);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp
.announce(signedTransaction)
.subscribe((x) => console.log(x), (err) => console.error(err));
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash = '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = companyAccount.sign(aggregateTransaction, networkGenerationHash);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp
.announce(signedTransaction)
.subscribe((x) => console.log(x), (err) => console.error(err));
symbol-cli transaction mosaicmetadata --target-address TCM6YD-BC3BW2-ZYXOXC-HHIRDV-MEZUIP-BRISYI-TPQ --mosaic-id 2C08D5EDB652AA79 --key BC2FC3ACFF58FF89 --value US00000000
Did you find what you were looking for? Give us your feedback.