別のアカウントがモザイクに制限を追加できるようにします。
別の会社の ComfyClothingCompany は STO を実施しようとしています。このケースでは、彼らは KYC & AML に特化した会社に KYC プロセスを委任したい と考えています。
前のガイド ( モザイク転送を制限する ) に従っている場合は、グローバル モザイク制限 に一致するように異なるキー値を組み合わせて、アカウントが特定のモザイクのトランザクションを制限する方法がわかるでしょう。
このガイドでは、KYC プロバイダーが許可していない場合において、アカウント間の cc.shares
- ComfyClothingCompany が作成したモザイク - の取引を制限します。
1. Start by creating a new restrictable
mosaic with the ComfyClothingCompany account account.
We will refer to this mosaic from now on as cc.shares
.
symbol-cli transaction mosaic --amount 1000000 --transferable --supply-mutable --restrictable --divisibility 0 --non-expiring --profile cccompany --sync
The new mosaic id is: 7cdf3b117a3c40cc
KYC プロバイダは kyc
という新しい名前のモザイクを登録し、そのモザイクにグローバル制限 { kyc, IsVerified, EQ, 1}
をモザイクに追加します。
const networkType = NetworkType.TEST_NET;
// replace with kyc provider private key
const kycProviderPrivateKey =
'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB';
const kycProviderAccount = Account.createFromPrivateKey(
kycProviderPrivateKey,
networkType,
);
// Define KYC Mosaic Id
const mosaicNonce = MosaicNonce.createRandom();
const mosaicDefinitionTransaction = MosaicDefinitionTransaction.create(
Deadline.create(epochAdjustment),
mosaicNonce,
MosaicId.createFromNonce(
mosaicNonce,
kycProviderAccount.publicAccount.address,
),
MosaicFlags.create(true, true, true),
0,
UInt64.fromUint(0),
networkType,
);
console.log('KYC MosaicId:', mosaicDefinitionTransaction.mosaicId.toHex());
// Define Mosaic global restriction Is_Verified = 1
const key = KeyGenerator.generateUInt64Key('IsVerified'.toLowerCase());
const mosaicGlobalRestrictionTransaction = MosaicGlobalRestrictionTransaction.create(
Deadline.create(epochAdjustment),
mosaicDefinitionTransaction.mosaicId, // mosaicId
key, // restictionKey
UInt64.fromUint(0), // previousRestrictionValue
MosaicRestrictionType.NONE, // previousRestrictionType
UInt64.fromUint(1), // newRestrictionValue
MosaicRestrictionType.EQ, // newRestrictionType
networkType,
);
const aggregateTransaction = AggregateTransaction.createComplete(
Deadline.create(epochAdjustment),
[
mosaicDefinitionTransaction.toAggregate(kycProviderAccount.publicAccount),
mosaicGlobalRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
],
networkType,
[],
UInt64.fromUint(2000000),
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = kycProviderAccount.sign(
aggregateTransaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with kyc provider private key
const kycProviderPrivateKey =
'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB';
const kycProviderAccount = symbol_sdk_1.Account.createFromPrivateKey(
kycProviderPrivateKey,
networkType,
);
// Define KYC Mosaic Id
const mosaicNonce = symbol_sdk_1.MosaicNonce.createRandom();
const mosaicDefinitionTransaction = symbol_sdk_1.MosaicDefinitionTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
mosaicNonce,
symbol_sdk_1.MosaicId.createFromNonce(
mosaicNonce,
kycProviderAccount.publicAccount.address,
),
symbol_sdk_1.MosaicFlags.create(true, true, true),
0,
symbol_sdk_1.UInt64.fromUint(0),
networkType,
);
console.log('KYC MosaicId:', mosaicDefinitionTransaction.mosaicId.toHex());
// Define Mosaic global restriction Is_Verified = 1
const key = symbol_sdk_1.KeyGenerator.generateUInt64Key(
'IsVerified'.toLowerCase(),
);
const mosaicGlobalRestrictionTransaction = symbol_sdk_1.MosaicGlobalRestrictionTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
mosaicDefinitionTransaction.mosaicId, // mosaicId
key, // restictionKey
symbol_sdk_1.UInt64.fromUint(0), // previousRestrictionValue
symbol_sdk_1.MosaicRestrictionType.NONE, // previousRestrictionType
symbol_sdk_1.UInt64.fromUint(1), // newRestrictionValue
symbol_sdk_1.MosaicRestrictionType.EQ, // newRestrictionType
networkType,
);
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createComplete(
symbol_sdk_1.Deadline.create(epochAdjustment),
[
mosaicDefinitionTransaction.toAggregate(kycProviderAccount.publicAccount),
mosaicGlobalRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
],
networkType,
[],
symbol_sdk_1.UInt64.fromUint(2000000),
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = kycProviderAccount.sign(
aggregateTransaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
KYC プロバイダは次の権限層を定義します。
キー |
操作者 |
値 |
説明 |
---|---|---|---|
IsVerified |
EQ |
1 |
クライアントが有効なパスポートを発行しました。 |
IsVerified |
EQ |
2 |
クライアントは有効な住所証明とパスポートを発行しました。 |
ComfyClothingCompany は制限 {cc.shares, kyc::IsVerified, EQ = 2}
付きのアカウントのみが株式を譲渡できるように決定します。このため、同社はモザイクのグローバル制限 {kyc::IsVerified, EQ, 2}
をモザイクの ccf.shares
に追加します。別のモザイクから制限を実装するにはフィールド referenceId
を使用します。
MosaicGlobalRestrictionTransaction をアナウンスして cc.shares
を targetMosaicId
、kyc
を referenceMosaicId
、 IsVerified
をキーとして設定します。
// replace with cc.shares mosaic id
const sharesIdHex = '7cdf3b117a3c40cc';
const sharesId = new MosaicId(sharesIdHex);
// replace with kyc mosaic id
const kycIdHex = '183D0802BCDB97AF';
const kycId = new MosaicId(kycIdHex);
// replace with network type
const networkType = NetworkType.TEST_NET;
const key = KeyGenerator.generateUInt64Key('IsVerified'.toLowerCase());
const transaction = MosaicGlobalRestrictionTransaction.create(
Deadline.create(epochAdjustment),
sharesId, // mosaicId
key, // restictionKey
UInt64.fromUint(0), // previousRestrictionValue
MosaicRestrictionType.NONE, // previousRestrictionType
UInt64.fromUint(2), // newRestrictionValue
MosaicRestrictionType.EQ, // newRestrictionType
networkType,
kycId, // referenceMosaicId
UInt64.fromUint(2000000),
);
const comfyClothingCompanyPrivateKey =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const comfyClothingCompanyAccount = Account.createFromPrivateKey(
comfyClothingCompanyPrivateKey,
networkType,
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = comfyClothingCompanyAccount.sign(
transaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
// replace with cc.shares mosaic id
const sharesIdHex = '7cdf3b117a3c40cc';
const sharesId = new symbol_sdk_1.MosaicId(sharesIdHex);
// replace with kyc mosaic id
const kycIdHex = '183D0802BCDB97AF';
const kycId = new symbol_sdk_1.MosaicId(kycIdHex);
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
const key = symbol_sdk_1.KeyGenerator.generateUInt64Key(
'IsVerified'.toLowerCase(),
);
const transaction = symbol_sdk_1.MosaicGlobalRestrictionTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
sharesId, // mosaicId
key, // restictionKey
symbol_sdk_1.UInt64.fromUint(0), // previousRestrictionValue
symbol_sdk_1.MosaicRestrictionType.NONE, // previousRestrictionType
symbol_sdk_1.UInt64.fromUint(2), // newRestrictionValue
symbol_sdk_1.MosaicRestrictionType.EQ, // newRestrictionType
networkType,
kycId, // referenceMosaicId
symbol_sdk_1.UInt64.fromUint(2000000),
);
const comfyClothingCompanyPrivateKey =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const comfyClothingCompanyAccount = symbol_sdk_1.Account.createFromPrivateKey(
comfyClothingCompanyPrivateKey,
networkType,
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = comfyClothingCompanyAccount.sign(
transaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
KYC プロバイダーは 3 人の潜在的投資家と出会いました。
Alice は有効なパスポートを提供しますがアドレスの証明は提供しません。KYC プロバイダは Alice のアカウントにモザイク制限の {kyc, IsVerified, 1}
を授与します。
Bob は有効なパスポートと住所証明を提供します。KYC プロバイダは Bob のアカウントにモザイク制限の {kyc, IsVerified, 2}
を授与します。
Carol は有効なパスポートと住所証明を提供します。KYC プロバイダは Carol のアカウントにモザイク制限の {kyc, IsVerified, 2}
を授与します。
KYC プロバイダーはモザイクアドレス制限を送信するアカウントに応じたタグを付ける必要があります。
// replace with kyc mosaic id
const mosaicIdHex = '183D0802BCDB97AF';
const mosaicId = new MosaicId(mosaicIdHex);
// replace with alice address
const aliceRawAddress = 'TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
const aliceAddress = Address.createFromRawAddress(aliceRawAddress);
// replace with bob address
const bobRawAddress = 'TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ';
const bobAddress = Address.createFromRawAddress(bobRawAddress);
// replace with carol address
const carolRawAddress = 'TCF7MK-FL6QYF-UHWVRZ-6UUCLN-YBDWLQ-ZZC37A-2O6R';
const carolAddress = Address.createFromRawAddress(carolRawAddress);
// replace with network type
const networkType = NetworkType.TEST_NET;
const key = KeyGenerator.generateUInt64Key('IsVerified'.toLowerCase());
const aliceMosaicAddressRestrictionTransaction = MosaicAddressRestrictionTransaction.create(
Deadline.create(epochAdjustment),
mosaicId, // mosaicId
key, // restrictionKey
aliceAddress, // address
UInt64.fromUint(1), // newRestrictionValue
networkType,
);
const bobMosaicAddressRestrictionTransaction = MosaicAddressRestrictionTransaction.create(
Deadline.create(epochAdjustment),
mosaicId, // mosaicId
key, // restrictionKey
bobAddress, // address
UInt64.fromUint(2), // newRestrictionValue
networkType,
);
const carolMosaicAddressRestrictionTransaction = MosaicAddressRestrictionTransaction.create(
Deadline.create(epochAdjustment),
mosaicId, // mosaicId
key, // restrictionKey
carolAddress, // address
UInt64.fromUint(2), // newRestrictionValue
networkType,
);
// replace with kyc provider private key
const kycProviderPrivateKey =
'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB';
const kycProviderAccount = Account.createFromPrivateKey(
kycProviderPrivateKey,
networkType,
);
const aggregateTransaction = AggregateTransaction.createComplete(
Deadline.create(epochAdjustment),
[
aliceMosaicAddressRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
bobMosaicAddressRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
carolMosaicAddressRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
],
networkType,
[],
UInt64.fromUint(2000000),
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = kycProviderAccount.sign(
aggregateTransaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
// replace with kyc mosaic id
const mosaicIdHex = '183D0802BCDB97AF';
const mosaicId = new symbol_sdk_1.MosaicId(mosaicIdHex);
// replace with alice address
const aliceRawAddress = 'TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
const aliceAddress = symbol_sdk_1.Address.createFromRawAddress(aliceRawAddress);
// replace with bob address
const bobRawAddress = 'TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ';
const bobAddress = symbol_sdk_1.Address.createFromRawAddress(bobRawAddress);
// replace with carol address
const carolRawAddress = 'TCF7MK-FL6QYF-UHWVRZ-6UUCLN-YBDWLQ-ZZC37A-2O6R';
const carolAddress = symbol_sdk_1.Address.createFromRawAddress(carolRawAddress);
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
const key = symbol_sdk_1.KeyGenerator.generateUInt64Key(
'IsVerified'.toLowerCase(),
);
const aliceMosaicAddressRestrictionTransaction = symbol_sdk_1.MosaicAddressRestrictionTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
mosaicId, // mosaicId
key, // restrictionKey
aliceAddress, // address
symbol_sdk_1.UInt64.fromUint(1), // newRestrictionValue
networkType,
);
const bobMosaicAddressRestrictionTransaction = symbol_sdk_1.MosaicAddressRestrictionTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
mosaicId, // mosaicId
key, // restrictionKey
bobAddress, // address
symbol_sdk_1.UInt64.fromUint(2), // newRestrictionValue
networkType,
);
const carolMosaicAddressRestrictionTransaction = symbol_sdk_1.MosaicAddressRestrictionTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
mosaicId, // mosaicId
key, // restrictionKey
carolAddress, // address
symbol_sdk_1.UInt64.fromUint(2), // newRestrictionValue
networkType,
);
// replace with kyc provider private key
const kycProviderPrivateKey =
'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB';
const kycProviderAccount = symbol_sdk_1.Account.createFromPrivateKey(
kycProviderPrivateKey,
networkType,
);
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createComplete(
symbol_sdk_1.Deadline.create(epochAdjustment),
[
aliceMosaicAddressRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
bobMosaicAddressRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
carolMosaicAddressRestrictionTransaction.toAggregate(
kycProviderAccount.publicAccount,
),
],
networkType,
[],
symbol_sdk_1.UInt64.fromUint(2000000),
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = kycProviderAccount.sign(
aggregateTransaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
5. After the restrictions get confirmed, Bob and Carol will be able to buy and send the cc.shares
units to each other.
But Alice—who has not provided valid proof of address—will not be able to receive shares.