このガイドでは、マルチシグアカウントからトランザクションを発行する方法を説明します。
AggregateCompleteTransaction の送信
この例では、Alice と Bob は 1-of-2 マルチシグ アカウントの署名者です。このマルチシグ構成により、Alice と Bob は別のアカウントでアセットを共有することができ、トランザクションにはいずれかの署名のみが必要です。
10 symbol.xym を共有アカウントから3番目のアドレスへ送信しましょう。
symbol.xym 単位を入金します。symbol.xym 単位を入金してください。
// replace network type
const networkType = NetworkType.TEST_NET;
// replace with cosignatory private key
const cosignatoryPrivateKey =
'0000000000000000000000000000000000000000000000000000000000000000';
const cosignatoryAccount = Account.createFromPrivateKey(
cosignatoryPrivateKey,
networkType,
);
// replace with multisig account public key
const multisigAccountPublicKey =
'3A537D5A1AF51158C42F80A199BB58351DBF3253C4A6A1B7BD1014682FB595EA';
const multisigAccount = PublicAccount.createFromPublicKey(
multisigAccountPublicKey,
networkType,
);
// replace with recipient address
const recipientRawAddress = 'TCWYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI';
const recipientAddress = Address.createFromRawAddress(recipientRawAddress);
// replace with symbol.xym id
const networkCurrencyMosaicId = new MosaicId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;
// replace network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with cosignatory private key
const cosignatoryPrivateKey =
'0000000000000000000000000000000000000000000000000000000000000000';
const cosignatoryAccount = symbol_sdk_1.Account.createFromPrivateKey(
cosignatoryPrivateKey,
networkType,
);
// replace with multisig account public key
const multisigAccountPublicKey =
'3A537D5A1AF51158C42F80A199BB58351DBF3253C4A6A1B7BD1014682FB595EA';
const multisigAccount = symbol_sdk_1.PublicAccount.createFromPublicKey(
multisigAccountPublicKey,
networkType,
);
// replace with recipient address
const recipientRawAddress = 'TCWYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI';
const recipientAddress = symbol_sdk_1.Address.createFromRawAddress(
recipientRawAddress,
);
// replace with symbol.xym id
const networkCurrencyMosaicId = new symbol_sdk_1.MosaicId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;
NetworkType networkType = repositoryFactory.getNetworkType().toFuture().get();
// replace with cosignatory private key
String cosignatoryPrivateKey = "";
Account cosignatoryAccount = Account.createFromPrivateKey(cosignatoryPrivateKey, networkType);
// replace with cosignatory private key
String multisigAccountPublicKey = "";
Account multisigAccount = Account.createFromPrivateKey(multisigAccountPublicKey, networkType);
// replace with recipient address
String recipientRawAddress = "TCWYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI";
Address recipientAddress = Address.createFromRawAddress(recipientRawAddress);
NetworkCurrency networkCurrency = repositoryFactory.getNetworkCurrency().toFuture().get();
| プロパティ | 値 |
|---|---|
| タイプ | TransferTransaction |
| Recipient | トランザクションを受け取るアカウントのアドレス |
| Mosaics | [10 symbol.xym] |
| メッセージ | 10 symbol.xym 送信 |
const transferTransaction = TransferTransaction.create(
Deadline.create(epochAdjustment),
recipientAddress,
[
new Mosaic(
networkCurrencyMosaicId,
UInt64.fromUint(10 * Math.pow(10, networkCurrencyDivisibility)),
),
],
PlainMessage.create('sending 10 symbol.xym'),
networkType,
);
const transferTransaction = symbol_sdk_1.TransferTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
recipientAddress,
[
new symbol_sdk_1.Mosaic(
networkCurrencyMosaicId,
symbol_sdk_1.UInt64.fromUint(
10 * Math.pow(10, networkCurrencyDivisibility),
),
),
],
symbol_sdk_1.PlainMessage.create('sending 10 symbol.xym'),
networkType,
);
const aggregateTransaction = AggregateTransaction.createComplete(
Deadline.create(epochAdjustment),
[transferTransaction.toAggregate(multisigAccount)],
networkType,
[],
UInt64.fromUint(2000000),
);
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createComplete(
symbol_sdk_1.Deadline.create(epochAdjustment),
[transferTransaction.toAggregate(multisigAccount)],
networkType,
[],
symbol_sdk_1.UInt64.fromUint(2000000),
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = cosignatoryAccount.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 = cosignatoryAccount.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 = cosignatoryAccount.sign(aggregateTransaction, generationHash);
try (Listener listener = repositoryFactory.createListener()) {
listener.open().get();
TransactionService transactionService = new TransactionServiceImpl(repositoryFactory);
transactionService.announce(listener, signedTransaction).toFuture().get();
}
今回は TransactionTransaction が AggregateCompleteTransaction でラップされています。これはトランザクションのアナウンスに必要なアカウントが 1 つだけのためです。トランザクションのアナウンスに複数の署名が必要な (たとえば 2-of-2 マルチシグアカウント) トランザクションはアグリゲート ボンデッド として定義する必要があり、また、他のすべての必要なマルチシグ参加者は、承認のために署名する必要があります。
const aggregateTransaction = AggregateTransaction.createBonded(
Deadline.create(epochAdjustment),
[transferTransaction.toAggregate(multisigAccount)],
networkType,
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = cosignatoryAccount.sign(
aggregateTransaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
const aggregateTransaction = symbol_sdk_1.AggregateTransaction.createBonded(
symbol_sdk_1.Deadline.create(epochAdjustment),
[transferTransaction.toAggregate(multisigAccount)],
networkType,
);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = cosignatoryAccount.sign(
aggregateTransaction,
networkGenerationHash,
);
console.log(signedTransaction.hash);
NetworkType networkType = repositoryFactory.getNetworkType().toFuture().get();
// replace with cosignatory private key
String cosignatoryPrivateKey = "";
Account cosignatoryAccount = Account.createFromPrivateKey(cosignatoryPrivateKey, networkType);
// replace with cosignatory private key
String multisigAccountPublicKey = "";
Account multisigAccount = Account.createFromPrivateKey(multisigAccountPublicKey, networkType);
// replace with recipient address
String recipientRawAddress = "TCWYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI";
Address recipientAddress = Address.createFromRawAddress(recipientRawAddress);
NetworkCurrency networkCurrency = repositoryFactory.getNetworkCurrency().toFuture().get();
TransferTransaction transferTransaction = TransferTransactionFactory.create(networkType, recipientAddress,
Collections.singletonList(networkCurrency.createRelative(BigInteger.valueOf(10))),
PlainMessage.create("sending 10 symbol.xym")).build();
AggregateTransaction aggregateTransaction = AggregateTransactionFactory.createBonded(networkType,
Collections.singletonList(transferTransaction.toAggregate(multisigAccount.getPublicAccount())))
.maxFee(BigInteger.valueOf(2000000)).build();
String generationHash = repositoryFactory.getGenerationHash().toFuture().get();
SignedTransaction signedTransaction = cosignatoryAccount.sign(aggregateTransaction, generationHash);
2. When an AggregateTransaction is bonded, an account needs to lock at least 10 symbol.xym to prevent spamming the network.
Once all cosigners sign the transaction, the amount of symbol.xym locked becomes available again in the account that has locked the funds.
After HashLockTransaction has been confirmed, announce the AggregateBondedTransaction with a cosignatory.
In our case, we will sign the transaction with Bob’s account.
const hashLockTransaction = HashLockTransaction.create(
Deadline.create(epochAdjustment),
new Mosaic(
networkCurrencyMosaicId,
UInt64.fromUint(10 * Math.pow(10, networkCurrencyDivisibility)),
),
UInt64.fromUint(480),
signedTransaction,
networkType,
UInt64.fromUint(2000000),
);
const signedHashLockTransaction = cosignatoryAccount.sign(
hashLockTransaction,
networkGenerationHash,
);
// replace with node endpoint
const nodeUrl = 'http://api-01.us-east-1.testnet.symboldev.network:3000';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const listener = repositoryFactory.createListener();
const receiptHttp = repositoryFactory.createReceiptRepository();
const transactionHttp = repositoryFactory.createTransactionRepository();
const transactionService = new TransactionService(transactionHttp, receiptHttp);
listener.open().then(() => {
transactionService
.announceHashLockAggregateBonded(
signedHashLockTransaction,
signedTransaction,
listener,
)
.subscribe(
(x) => console.log(x),
(err) => console.log(err),
() => listener.close(),
);
});
const hashLockTransaction = symbol_sdk_1.HashLockTransaction.create(
symbol_sdk_1.Deadline.create(epochAdjustment),
new symbol_sdk_1.Mosaic(
networkCurrencyMosaicId,
symbol_sdk_1.UInt64.fromUint(
10 * Math.pow(10, networkCurrencyDivisibility),
),
),
symbol_sdk_1.UInt64.fromUint(480),
signedTransaction,
networkType,
symbol_sdk_1.UInt64.fromUint(2000000),
);
const signedHashLockTransaction = cosignatoryAccount.sign(
hashLockTransaction,
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 listener = repositoryFactory.createListener();
const receiptHttp = repositoryFactory.createReceiptRepository();
const transactionHttp = repositoryFactory.createTransactionRepository();
const transactionService = new symbol_sdk_1.TransactionService(
transactionHttp,
receiptHttp,
);
listener.open().then(() => {
transactionService
.announceHashLockAggregateBonded(
signedHashLockTransaction,
signedTransaction,
listener,
)
.subscribe(
(x) => console.log(x),
(err) => console.log(err),
() => listener.close(),
);
});
HashLockTransaction hashLockTransaction = HashLockTransactionFactory
.create(networkType, networkCurrency.createRelative(BigDecimal.valueOf(10)), BigInteger.valueOf(480),
signedTransaction).build();
SignedTransaction signedHashLockTransaction = cosignatoryAccount.sign(hashLockTransaction, generationHash);
try (Listener listener = repositoryFactory.createListener()) {
listener.open().get();
TransactionService transactionService = new TransactionServiceImpl(repositoryFactory);
transactionService
.announceHashLockAggregateBonded(listener, signedHashLockTransaction, signedTransaction).toFuture()
.get();
}
トランザクションに署名するには (2) のトランザクションハッシュを置き換えて CLI コマンド transaction cosign を使用します。
symbol-cli transaction cosign --hash A6A374E66B32A3D5133018EFA9CD6E3169C8EEA339F7CCBE29C47D07086E068C --profile alice
minApproval 分の署名が集まると、受取者は資金を受け取るでしょう。そして 10 symbol.xym をロックしているアカウントには、ロックされた資金が返還されます。お探しのものは見つかりましたか? フィードバックをください。