Delegar restricciones de tokens a un tercero

Permita que otra cuenta agregue restricciones a sus tokens.

caso de uso

Otra empresa, ComfyClothingCompany quiere realizar una STO. En este caso, quieren delegar el proceso KYC a una empresa especializada en KYC y AML.

Si ha seguido la guía anterior (restricción de transferencias de tokens), sabe cómo restringir las cuentas para que no realicen transacciones con un token determinado combinando diferentes valores-clave para que coincidan con el :doc:` global. restricción de tokens <../../concepts/token-restriction>`.

../../_images/delegated-token-restriction-sto.png

Use case diagram

En esta guía, restringiremos las cuentas para operar con cc.shares (token creado por ComfyClothingCompany) si el proveedor de KYC no lo permite.

requisitos previos

Método #01: Uso del SDK

1. Comience creando un nuevo token restringible, Nos referiremos a este token de ahora en adelante como cc.shares.

bitxor-cli transaction token --amount 1000000 --transferable --supply-mutable --restrictable --divisibility 0 --non-expiring --profile cccompany --sync

The new token id is: 7cdf3b117a3c40cc
  1. El proveedor de KYC registra un nuevo token llamado kyc y agrega la restricción global de token { kyc, IsVerified, EQ, 1} al token.

const networkType = NetworkType.TEST_NET;
// replace with kyc provider private key
const kycProviderPrivateKey =
  'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB';
const kycProviderAccount = Account.createFromPrivateKey(
  kycProviderPrivateKey,
  networkType,
);

// Define KYC Token Id
const tokenNonce = TokenNonce.createRandom();
const tokenDefinitionTransaction = TokenDefinitionTransaction.create(
  Deadline.create(epochAdjustment),
  tokenNonce,
  TokenId.createFromNonce(
    tokenNonce,
    kycProviderAccount.publicAccount.address,
  ),
  TokenFlags.create(true, true, true),
  0,
  UInt64.fromUint(0),
  networkType,
);
console.log('KYC TokenId:', tokenDefinitionTransaction.tokenId.toHex());

// Define Token global restriction Is_Verified = 1
const key = KeyGenerator.generateUInt64Key('IsVerified'.toLowerCase());
const tokenGlobalRestrictionTransaction = TokenGlobalRestrictionTransaction.create(
  Deadline.create(epochAdjustment),
  tokenDefinitionTransaction.tokenId, // tokenId
  key, // restictionKey
  UInt64.fromUint(0), // previousRestrictionValue
  TokenRestrictionType.NONE, // previousRestrictionType
  UInt64.fromUint(1), // newRestrictionValue
  TokenRestrictionType.EQ, // newRestrictionType
  networkType,
);

const aggregateTransaction = AggregateTransaction.createComplete(
  Deadline.create(epochAdjustment),
  [
    tokenDefinitionTransaction.toAggregate(kycProviderAccount.publicAccount),
    tokenGlobalRestrictionTransaction.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 = bitxor_sdk_1.NetworkType.TEST_NET;
// replace with kyc provider private key
const kycProviderPrivateKey =
  'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB';
const kycProviderAccount = bitxor_sdk_1.Account.createFromPrivateKey(
  kycProviderPrivateKey,
  networkType,
);
// Define KYC Token Id
const tokenNonce = bitxor_sdk_1.TokenNonce.createRandom();
const tokenDefinitionTransaction = bitxor_sdk_1.TokenDefinitionTransaction.create(
  bitxor_sdk_1.Deadline.create(epochAdjustment),
  tokenNonce,
  bitxor_sdk_1.TokenId.createFromNonce(
    tokenNonce,
    kycProviderAccount.publicAccount.address,
  ),
  bitxor_sdk_1.TokenFlags.create(true, true, true),
  0,
  bitxor_sdk_1.UInt64.fromUint(0),
  networkType,
);
console.log('KYC TokenId:', tokenDefinitionTransaction.tokenId.toHex());
// Define Token global restriction Is_Verified = 1
const key = bitxor_sdk_1.KeyGenerator.generateUInt64Key(
  'IsVerified'.toLowerCase(),
);
const tokenGlobalRestrictionTransaction = bitxor_sdk_1.TokenGlobalRestrictionTransaction.create(
  bitxor_sdk_1.Deadline.create(epochAdjustment),
  tokenDefinitionTransaction.tokenId, // tokenId
  key, // restictionKey
  bitxor_sdk_1.UInt64.fromUint(0), // previousRestrictionValue
  bitxor_sdk_1.TokenRestrictionType.NONE, // previousRestrictionType
  bitxor_sdk_1.UInt64.fromUint(1), // newRestrictionValue
  bitxor_sdk_1.TokenRestrictionType.EQ, // newRestrictionType
  networkType,
);
const aggregateTransaction = bitxor_sdk_1.AggregateTransaction.createComplete(
  bitxor_sdk_1.Deadline.create(epochAdjustment),
  [
    tokenDefinitionTransaction.toAggregate(kycProviderAccount.publicAccount),
    tokenGlobalRestrictionTransaction.toAggregate(
      kycProviderAccount.publicAccount,
    ),
  ],
  networkType,
  [],
  bitxor_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 bitxor_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
  (x) => console.log(x),
  (err) => console.error(err),
);

El proveedor de KYC define los siguientes niveles de permisos:

Key

Operator

Value

Description

IsVerified

EQ

1

The client has issued a valid passport.

IsVerified

EQ

2

The client has issued a valid proof of address and passport.

ComfyClothingCompany decide que solo las cuentas con la restricción {cc.shares, kyc::IsVerified, EQ = 2} deben habilitarse para transferir acciones. Por esta razón, la empresa agrega la restricción global del token { kyc::IsVerified, EQ, 2} al token ccf.shares. Para implementar la restricción desde otro token, utilice el campo referenceId.

  1. Anuncie una TokenGlobalRestrictionTransaction, configurando cc.shares como targetTokenId, kyc como referenceTokenId y IsVerified como clave.

// replace with cc.shares token id
const sharesIdHex = '7cdf3b117a3c40cc';
const sharesId = new TokenId(sharesIdHex);
// replace with kyc token id
const kycIdHex = '183D0802BCDB97AF';
const kycId = new TokenId(kycIdHex);
// replace with network type
const networkType = NetworkType.TEST_NET;

const key = KeyGenerator.generateUInt64Key('IsVerified'.toLowerCase());

const transaction = TokenGlobalRestrictionTransaction.create(
  Deadline.create(epochAdjustment),
  sharesId, // tokenId
  key, // restictionKey
  UInt64.fromUint(0), // previousRestrictionValue
  TokenRestrictionType.NONE, // previousRestrictionType
  UInt64.fromUint(2), // newRestrictionValue
  TokenRestrictionType.EQ, // newRestrictionType
  networkType,
  kycId, // referenceTokenId
  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 token id
const sharesIdHex = '7cdf3b117a3c40cc';
const sharesId = new bitxor_sdk_1.TokenId(sharesIdHex);
// replace with kyc token id
const kycIdHex = '183D0802BCDB97AF';
const kycId = new bitxor_sdk_1.TokenId(kycIdHex);
// replace with network type
const networkType = bitxor_sdk_1.NetworkType.TEST_NET;
const key = bitxor_sdk_1.KeyGenerator.generateUInt64Key(
  'IsVerified'.toLowerCase(),
);
const transaction = bitxor_sdk_1.TokenGlobalRestrictionTransaction.create(
  bitxor_sdk_1.Deadline.create(epochAdjustment),
  sharesId, // tokenId
  key, // restictionKey
  bitxor_sdk_1.UInt64.fromUint(0), // previousRestrictionValue
  bitxor_sdk_1.TokenRestrictionType.NONE, // previousRestrictionType
  bitxor_sdk_1.UInt64.fromUint(2), // newRestrictionValue
  bitxor_sdk_1.TokenRestrictionType.EQ, // newRestrictionType
  networkType,
  kycId, // referenceTokenId
  bitxor_sdk_1.UInt64.fromUint(2000000),
);
const comfyClothingCompanyPrivateKey =
  'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const comfyClothingCompanyAccount = bitxor_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 bitxor_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
  (x) => console.log(x),
  (err) => console.error(err),
);
  1. El proveedor de KYC se ha encontrado con tres inversores potenciales:

  • Alice proporciona un pasaporte válido pero no prueba de domicilio. El proveedor de KYC otorga a la cuenta de Alice la restricción de token {kyc, IsVerified, 1}.

  • Bob proporciona un pasaporte válido y comprobante de domicilio. El proveedor de KYC otorga a la cuenta de Bob la restricción de token {kyc, IsVerified, 2}.

  • Carol proporciona un pasaporte válido y comprobante de domicilio. El proveedor de KYC otorga a la cuenta de Carol la restricción de token {kyc, IsVerified, 2}.

El proveedor de KYC tiene que etiquetar las cuentas en consecuencia enviando restricciones de dirección de token. .. example-code:

.. viewsource:: ../../resources/examples/typescript/restriction/RestrictingTokensTransfersDelegatedTokenAddressRestriction.ts
    :language: typescript
    :start-after:  /* start block 01 */
    :end-before: /* end block 01 */

.. viewsource:: ../../resources/examples/typescript/restriction/RestrictingTokensTransfersDelegatedTokenAddressRestriction.js
    :language: javascript
    :start-after:  /* start block 01 */
    :end-before: /* end block 01 */

5. Después de que se confirmen las restricciones, Bob y Carol podrán comprar y enviarse las unidades cc.shares. Pero Alice�? que no ha proporcionado un comprobante de domicilio válido�? no podrá recibir acciones.