複数のトランザクションを同時に送信

異なるアカウントへトランザクションを同時に送信するには、アグリゲートトランザクションを使用します。

ユースケース

Dan は Alice と Bob にモザイクを送ろうとしています。彼は 2 つの TransferTransactions でそれを実行できます。しかし、 Alice と Bob が同時に資産を受領することを確実にするために AggregateTransaction を定義します。

../../_images/aggregate-sending-payouts1.png

異なる複数の受信者にトランザクションをアトミックに送信する

前提条件

方法 #01: SDK を使用する

  1. 新しいファイルを作成して、10 symbol.xym を異なる受信者へ送るための 2 つの transfer transactions を定義します。
// replace with network type
const networkType = NetworkType.TEST_NET;
// replace with sender private key
const privateKey =
  'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
const account = Account.createFromPrivateKey(privateKey, networkType);
// replace with address
const aliceAddress = 'TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
const aliceAccount = Address.createFromRawAddress(aliceAddress);
// replace with address
const bobAddress = 'TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ';
const bobAccount = Address.createFromRawAddress(bobAddress);
// replace with symbol.xym id
const networkCurrencyMosaicId = new MosaicId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;

const mosaic = new Mosaic(
  networkCurrencyMosaicId,
  UInt64.fromUint(10 * Math.pow(10, networkCurrencyDivisibility)),
);

const aliceTransferTransaction = TransferTransaction.create(
  Deadline.create(123456789),
  aliceAccount,
  [mosaic],
  PlainMessage.create('payout'),
  networkType,
);
const bobTransferTransaction = TransferTransaction.create(
  Deadline.create(123456789),
  bobAccount,
  [mosaic],
  PlainMessage.create('payout'),
  networkType,
);
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with sender private key
const privateKey =
  'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
const account = symbol_sdk_1.Account.createFromPrivateKey(
  privateKey,
  networkType,
);
// replace with address
const aliceAddress = 'TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
const aliceAccount = symbol_sdk_1.Address.createFromRawAddress(aliceAddress);
// replace with address
const bobAddress = 'TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ';
const bobAccount = symbol_sdk_1.Address.createFromRawAddress(bobAddress);
// replace with symbol.xym id
const networkCurrencyMosaicId = new symbol_sdk_1.MosaicId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;
const mosaic = new symbol_sdk_1.Mosaic(
  networkCurrencyMosaicId,
  symbol_sdk_1.UInt64.fromUint(10 * Math.pow(10, networkCurrencyDivisibility)),
);
const aliceTransferTransaction = symbol_sdk_1.TransferTransaction.create(
  symbol_sdk_1.Deadline.create(123456789),
  aliceAccount,
  [mosaic],
  symbol_sdk_1.PlainMessage.create('payout'),
  networkType,
);
const bobTransferTransaction = symbol_sdk_1.TransferTransaction.create(
  symbol_sdk_1.Deadline.create(123456789),
  bobAccount,
  [mosaic],
  symbol_sdk_1.PlainMessage.create('payout'),
  networkType,
);
            NetworkType networkType = repositoryFactory.getNetworkType().toFuture().get();

            // replace with sender private key
            String privateKey = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
            Account account = Account.createFromPrivateKey(privateKey, networkType);
            // replace with address
            String aliceAddress = "TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I";
            Address aliceAccount = Address.createFromRawAddress(aliceAddress);
            // replace with address
            String bobAddress = "TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ";
            Address bobAccount = Address.createFromRawAddress(bobAddress);

            NetworkCurrency networkCurrency = repositoryFactory.getNetworkCurrency().toFuture().get();

            Mosaic mosaic = networkCurrency.createRelative(BigDecimal.valueOf(10));

            TransferTransaction aliceTransferTransaction = TransferTransactionFactory
                .create(networkType, aliceAccount, Collections.singletonList(mosaic), PlainMessage.create("payout"))
                .build();

            TransferTransaction bobTransferTransaction = TransferTransactionFactory
                .create(networkType, bobAccount, Collections.singletonList(mosaic), PlainMessage.create("payout"))
                .build();
  1. 両方のトランザクションを AggregateTransaction でラップし、Dan の公開アカウントを必要な署名者として追加します。1 つの秘密鍵 - Dan のアカウント - でアグリゲート内のすべてのトランザクションに署名できるため、トランザクションを コンプリート として定義できます。
const aggregateTransaction = AggregateTransaction.createComplete(
  Deadline.create(123456789),
  [
    aliceTransferTransaction.toAggregate(account.publicAccount),
    bobTransferTransaction.toAggregate(account.publicAccount),
  ],
  networkType,
  [],
  UInt64.fromUint(2000000),
);
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createComplete(
  symbol_sdk_1.Deadline.create(123456789),
  [
    aliceTransferTransaction.toAggregate(account.publicAccount),
    bobTransferTransaction.toAggregate(account.publicAccount),
  ],
  networkType,
  [],
  symbol_sdk_1.UInt64.fromUint(2000000),
);
            AggregateTransaction aggregateTransaction = AggregateTransactionFactory.createComplete(networkType, Arrays
                .asList(aliceTransferTransaction.toAggregate(account.getPublicAccount()),
                    bobTransferTransaction.toAggregate(account.getPublicAccount()))).maxFee(BigInteger.valueOf(2000000))
                .build();
  1. Dan のアカウントでトランザクションへ署名してアナウンスをします。
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
  '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = account.sign(
  aggregateTransaction,
  networkGenerationHash,
);
// replace with node endpoint
const nodeUrl = 'http://api-01.us-east-1.testnet.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 = account.sign(
  aggregateTransaction,
  networkGenerationHash,
);
// replace with node endpoint
const nodeUrl = 'http://api-01.us-east-1.testnet.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),
);
            String generationHash = repositoryFactory.getGenerationHash().toFuture().get();
            SignedTransaction signedTransaction = account.sign(aggregateTransaction, generationHash);

            try (Listener listener = repositoryFactory.createListener()) {
                listener.open().get();
                TransactionService transactionService = new TransactionServiceImpl(repositoryFactory);
                transactionService.announce(listener, signedTransaction).toFuture().get();

            }