Skip to content

Examples: Off chain AggregateComplete

Chun Lam edited this page Feb 21, 2024 · 4 revisions

Let say, as example, Alice and Bob wanted to exchange 2 asset between them. Without using on-chain cosign, they can do a off-chain cosign.

import { NetworkType, Mosaic, PlainMessage, Deadline, TransferTransaction, SignedTransaction,
    Account, PublicAccount, TransactionHttp, NamespaceId, UInt64, AggregateTransaction, TransactionMapping, 
    CosignatureTransaction, CosignatureSignedTransaction, AggregateTransactionService 
} from "tsjs-xpx-chain-sdk";

let networkType = NetworkType.TEST_NET;
const generationHash = "<please get it from 1st block>";
let apiUrl = "https://bctestnet1.brimstone.xpxsirius.io";

let transactionHttp = new TransactionHttp(apiUrl);

// Alice as initiator

let alicePrivateKey = "<alicePrivateKey>";
let bobPublicKey = "<bobPublicKey>";

let aliceAccount = Account.createFromPrivateKey(alicePrivateKey, networkType, 1);
let bobPublicAccount = PublicAccount.createFromPublicKey(bobPublicKey, networkType, 1);

let transferToBob = TransferTransaction.create(
    Deadline.create(), // default 2 hours
    bobPublicAccount.address,
    [
        new Mosaic(new NamespaceId("alicecoin"), UInt64.fromUint(10)) // sending 10 alicecoin via namespace
    ],
    PlainMessage.create("I am sending you 10 AliceCoin"),
    networkType
)

let transferToAlice = TransferTransaction.create(
    Deadline.create(), // default 2 hours
    aliceAccount.address,
    [
        new Mosaic(new NamespaceId("bobcoin"), UInt64.fromUint(10)) // sending 10 bobcoin via namespace
    ],
    PlainMessage.create("I am sending you 10 BobCoin"),
    networkType
)

// Aggregate both transaction together as Aggregate Complete
let aggregateTxn = AggregateTransaction.createCompleteV1(
    Deadline.create(),
    [
        transferToAlice.toAggregateV1(bobPublicAccount), // aggreagete and set bob account to sign this transaction
        transferToBob.toAggregateV1(aliceAccount.publicAccount), // aggreagete and set Alice account to sign this transaction
    ],
    networkType
)

// Alice sign the aggregateTxn
let aliceSignedAggregateTxn = aliceAccount.preV2Sign(aggregateTxn, generationHash);

// Not announcing the transaction directly, as it will fail, it does not have the complete signature
let payloadToCosign = aliceSignedAggregateTxn.payload;

// send the payload to Bob, it is a long hexadecimal string

// -------------------------------------------------------
// Here onward is Bob

// map back the payload to transaction, and review it
let transaction = TransactionMapping.createFromPayload(payloadToCosign); // might need to cast to AggregateTransaction instance

// if everything ok, cosign it
let bobAccount = Account.createFromPrivateKey("<bobPrivateKey>", networkType, 1);
let cosignedSignature = CosignatureTransaction.signTransactionPayload(bobAccount, payloadToCosign, generationHash);

const cosignedSignatureFromBob = cosignedSignature.signature // pass it back to Alice
cosignedSignature.signer // pass it back to Alice, optional

// alternatively, can announce the transaction by Bob directly after gathered all cosigners signature
let recreatedSignedTransaction = SignedTransaction.createFromPayload(payloadToCosign, generationHash);
let fullySignedAggregateTxn = AggregateTransactionService.addCosignatures(recreatedSignedTransaction, [cosignedSignature]);

transactionHttp.announce(fullySignedAggregateTxn);
// done, no need to pass back to Alice

//---------------------------------------------------------
// Back to Alice

let cosignedSignedTransaction = CosignatureSignedTransaction.createFromAccVersion(aliceSignedAggregateTxn.hash, cosignedSignatureFromBob, 1, bobPublicAccount.publicKey);

let fullySignedAggregateTxn = AggregateTransactionService.addCosignatures(aliceSignedAggregateTxn, [cosignedSignedTransaction]);

// or you can recreate the transaction with the previous payload and sign again
let recreatedUnsignedTransaction = TransactionMapping.createFromPayload(payloadToCosign) as AggregateTransaction; // might need to cast to AggregateTransaction instance
let fullySignedAggregateTxn = recreatedUnsignedTransaction.signTransactionGivenSignaturesV1(aliceAccount, [cosignedSignedTransaction], generationHash);

// finally announce it 
transactionHttp.announce(fullySignedAggregateTxn);

// the rest is checking the transaction status