txwrapper icon indicating copy to clipboard operation
txwrapper copied to clipboard

[Question] Create Smart Contract call transaction offline and submit it later

Open evgeny-s opened this issue 4 years ago • 6 comments

Hey, guys. Thanks for this useful lib. Is it a possibility to create a Smart Contract call offline, wrap it to string let's say, share a transaction string (for example put it to DB), and later unwrap and submit it to the Blockchain?

Thanks!

evgeny-s avatar Jan 14 '21 12:01 evgeny-s

Hey 👋

I am actually not personally familiar with transactions for contracts, but if they are standard transactions (extrinsics), you can encode the transaction, which turns it into a SCALE encoded hex string.

You can store that hex string in a DB, and you can store it at various stages of construction and should still be able to decode it with polkadot-js and/or the utils from this lib to sign etc. Additionally, polkadot-js is pretty flexible when it comes into reading data so in many cases it can also read in a JSON representation of the transaction.

The final transaction is broadcasted as a hex string so you could easily store that in a DB as well and broadcast it as is.

emostov avatar Jan 15 '21 02:01 emostov

Hi.

Have you implemented the offline creation contract call?

azhu003 avatar May 11 '21 10:05 azhu003

Hello, @azhu003 Yes, I was able to do it using extrinsics and polkadot JS lib. Here is the example:

    this.appKeyring = keyring.addFromJson(
      JSON.parse(process.env.APP_WALLET_JSON)
    );

    const gasLimitAuto = -1;
    const anyValue = 0;
    const transferObj = await this.contract.tx.methodName(
      anyValue,
      gasLimitAuto,
      param1,
      param2,
      param3,
      param4,
      param5
    );

    return new Promise((res, rej) => {
      transferObj
        .signAndSend(this.appKeyring, ({ status }) => {
          if (status.isInBlock) {
            const hash = status.asInBlock.toHex();
            this.logger.log(`In block: ${hash}`);
            res(hash);
          }
        })
        .catch((err) => rej(err));
    });

evgeny-s avatar May 11 '21 12:05 evgeny-s

Above - online call. Below offline:

public async createSignedTransaction(
    privateKey: string,
    destination: string,
    amount: string,
  ): Promise<SignedDataResponse> {
    const gasLimitAuto = -1;
    const anyValue = 0;

    const keyring = new Keyring({type: this.userKeyRingType});
    const userKeyRing = keyring.addFromSeed(hexToU8a(privateKey));

    const tx = await this.contract.tx
      .transfer(anyValue, gasLimitAuto, destination, Number(amount), partialFee)
      .signAsync(userKeyRing);
    const txString = JSON.stringify(tx);
    const signedDataDto = new SignedDataResponse();
    signedDataDto.tx = txString;

    return signedDataDto;
  }


public async submitTx(tx: string, publicKey: string, appId: string): Promise<SubmitTransactionRes> {
    const txn = JSON.parse(tx);

    const txnHash = await this.substrateApi.rpc.author.submitExtrinsic(txn);
    const txnString = JSON.stringify(txnHash);
    const submitTxResponse = new SubmitTransactionRes(txnString);

    this.logger.log(`Tx hash: ${txnHash}`);

    return submitTxResponse;
  }

evgeny-s avatar May 11 '21 12:05 evgeny-s

@azhu003 Hope it helps.

evgeny-s avatar May 11 '21 12:05 evgeny-s

@evgeny-s thanks😁

azhu003 avatar May 11 '21 12:05 azhu003