Coder Social home page Coder Social logo

eth-sig-util's People

Contributors

ludowkm avatar njovy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

eth-sig-util's Issues

Could we get an example of valid jsonData for a TypedDataVersion.V4 call?

Specifically how the 'types' are mapped to valid Json for a TypedDataVersion.V4 call?

E/flutter ( 7237): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Invalid argument(s): jsonData format is not corresponding to TypedMessage
E/flutter ( 7237): #0      TypedDataUtil.hashMessage (package:eth_sig_util/util/typed_data.dart:45:9)
E/flutter ( 7237): #1      EthSigUtil.signTypedData (package:eth_sig_util/eth_sig_util.dart:26:27)

An example of the typed data I am trying to sign is on step three of this page https://docs.rarible.org/asset/creating-an-asset#erc721-lazy-minting

I have this, but I don't know how to format it properly for the signTypedData 'types' field.

"types": {
    "EIP712Domain" [
      {
        type: "string",
        name: "name",
      },
      {
        type: "string",
        name: "version",
      },
      {
        type: "uint256",
        name: "chainId",
      },
      {
        type: "address",
        name: "verifyingContract",
      }
    ],
    "Mint721": [
        { name: "tokenId", type: "uint256" },
        { name: "tokenURI", type: "string" },
        { name: "creators", type: "Part[]" },
        { name: "royalties", type: "Part[]" }
    ],
    "Part": [
        { name: "account", type: "address" },
        { name: "value", type: "uint96" }
    ]
},

Thanks for your time. Excited to see this package.

Invalid signTypedData v4 signature, does not match @metamask/eth-sig-util

While debugging #13, I recreated the flow to use USDC's transferWithAuthorization with node and @metamask/eth-sig-util. The same flow/code in dart does not generate the same signature.

JS
Here is a working js example that generates a signature like:
0xeef120842a7c11630aa1758d4291c2f36006afd813b2342570fcec9c12bc91970f57a6996ebc37ce006b100e7a93474d4add11c919ec05141342c8334e187fc71b, which I have successfully submitted to Ropsten.

const ethSigUtil = require("@metamask/eth-sig-util");
const { SignTypedDataVersion } = require("@metamask/eth-sig-util");

const usdcAddress = '0x07865c6e87b9f70255377e024ace6630c1eaa37f';
const privateKey = '04...100';
const pkBuffer = Buffer.from(privateKey, "hex");
const fromAddress = '0xd9d3768621774c3c357b9b5fcb23b5735ea2c7ae';
const toAddress = '0x33eeCb4A75C9241eEa0190e5dCDFb76D2Ed67613';
const amount = 1000000;
const validAfter = 0;
const validBefore = Math.floor(Date.now() / 1000) + 3600;
const nonce = web3.utils.randomHex(32);

const msgParams = {
    domain: {
      chainId: '3',
      name: 'USD Coin',
      verifyingContract: usdcAddress,
      version: '2',
    },
    message: {
        from: fromAddress,
        to: toAddress,
        value: amount,
        validAfter: validAfter,
        validBefore: validBefore,
        nonce: nonce
      },
    primaryType: 'TransferWithAuthorization',
    types: {
      EIP712Domain: [
        { name: 'name', type: 'string' },
        { name: 'version', type: 'string' },
        { name: 'chainId', type: 'uint256' },
        { name: 'verifyingContract', type: 'address' },
      ],
      TransferWithAuthorization: [
        { name: "from", type: "address" },
        { name: "to", type: "address" },
        { name: "value", type: "uint256" },
        { name: "validAfter", type: "uint256" },
        { name: "validBefore", type: "uint256" },
        { name: "nonce", type: "bytes32" }
      ]
    },
  };

let version = SignTypedDataVersion.V4;

const signature = ethSigUtil.signTypedData({privateKey: pkBuffer, data: msgParams, version: version});
console.log("Signature:" + signature);

Dart
Trying to emulate this same pattern in dart (using the same nonce and validBefore) generates a different and invalid signature:
0x150c45911e31162551b31dd7e50eb3104c6eef84d9d01c3405eb831ffd575d0b7809cb65d91b8adf8cd059508c6a075146c118c7df2415537103b888ebc969921b, which comes back with invalid signature from the contract call.

import 'package:eth_sig_util/eth_sig_util.dart';

const privateKey = '04...100';
const usdcAddress = '0x07865c6e87b9f70255377e024ace6630c1eaa37f';
const fromAddress = '0xd9d3768621774c3c357b9b5fcb23b5735ea2c7ae';
const toAddress = '0x33eeCb4A75C9241eEa0190e5dCDFb76D2Ed67613';
const amount = 1000000;
const validAfter = 0;
const validBefore = 1646931849; // logged from the js code
const nonce = "0xc150256aaf6f21cae3ce7f44804afa079681caa4dd86d1f0d9c05fe5f1a824ea"; // logged from the js code
const usdcAddress = '0x07865c6e87b9f70255377e024ace6630c1eaa37f';

    final msgParams = {
      "domain": {
        "chainId": '3',
        "name": 'USD Coin',
        "verifyingContract": usdcAddress,
        "version": '2',
      },
      "message": {
        "from": fromAddress,
        "to": toAddress,
        "value": amount,
        "validAfter": validAfter,
        "validBefore": validBefore,
        "nonce": nonce
      },
      "primaryType": 'TransferWithAuthorization',
      "types": {
        "EIP712Domain": [
          {"name": 'name', "type": 'string'},
          {"name": 'version', "type": 'string'},
          {"name": 'chainId', "type": 'uint256'},
          {"name": 'verifyingContract', "type": 'address'},
        ],
        "TransferWithAuthorization": [
          {"name": "from", "type": "address"},
          {"name": "to", "type": "address"},
          {"name": "value", "type": "uint256"},
          {"name": "validAfter", "type": "uint256"},
          {"name": "validBefore", "type": "uint256"},
          {"name": "nonce", "type": "bytes32"}
        ]
      },
    };

final jsonData = jsonEncode(msgParams);
String signature = EthSigUtil.signTypedData(privateKey: privateKey, jsonData: jsonData, version: TypedDataVersion.V4);
print("Signature: " + signature);

Why does this not work as expected?

Could not construct a recoverable key. This should never happen

final private =
EthPrivateKey.fromHex(WalletSp.instance.getCurrentPrivateKey());

final data = 'hello ๅ“ˆๅ“ˆ';

final sign1 = EthSigUtil.signPersonalMessage(privateKey: bytesToHex(private.privateKey),message: Uint8List.fromList(utf8.encode(data)));

logger('sign1:$sign1');


I reported this error by calling the signPersonalMessage function

Feature Request: Expose an Uint8List type for a private key

The library only takes a hex string for a private key and it requires to convert this string to an Uint8List whenever it calls a sign or recover.

Suggestion 1: Add a required named argument to all methods that takes a private key and change a string private key to optional. If an optional private key is set, then simply change this to bytes and call this method again.

Suggestion 2: Add a separate method that takes a private key as an Uint8List.

Invalid signature when using chainId with signTypedData

When debugging #13 I used one of the test cases as a starting point:

const privateKey = '4af1bceebf7f3634ec3cff8a2c38e51178d5d4ce585c52d6043e5e2cc3418bb0';
const json =
  r'''{"types":{"EIP712Domain":[{"type":"string","name":"name"},{"type":"string","name":"version"},{"type":"uint256","name":"chainId"},{"type":"address","name":"verifyingContract"}],"Part":[{"name":"account","type":"address"},{"name":"value","type":"uint96"}],"Mint721":[{"name":"tokenId","type":"uint256"},{"name":"tokenURI","type":"string"},{"name":"creators","type":"Part[]"},{"name":"royalties","type":"Part[]"}]},"domain":{"name":"Mint721","version":"1","chainId":4,"verifyingContract":"0x2547760120aed692eb19d22a5d9ccfe0f7872fce"},"primaryType":"Mint721","message":{"@type":"ERC721","contract":"0x2547760120aed692eb19d22a5d9ccfe0f7872fce","tokenId":"1","uri":"ipfs://ipfs/hash","creators":[{"account":"0xc5eac3488524d577a1495492599e8013b1f91efa","value":10000}],"royalties":[],"tokenURI":"ipfs://ipfs/hash"}}''';
  test('should sign data with custom type which has an array', () {
    final signature = EthSigUtil.signTypedData(privateKey: privateKey, jsonData: json, version: TypedDataVersion.V4);
    expect(signature,'0x2ce14898e255b8d1e5f296a293548607720951e507a5416a0515baef0420984f2e28df8824206db9dbab0e7f5b14eeb834d48ada4444e5f15e7bfd777d2069481c');
  });

This works as expected, but when adding the chainId parameter to the same test, and checking the sigParams:

String signature = EthSigUtil.signTypedData(privateKey: privateKey, jsonData: jsonTest, version: TypedDataVersion.V4, chainId: 280);
var sigParams = SignatureUtil.fromRpcSig(signature);

The result is an invalid signature length: "ArgumentError (Invalid argument(s): Invalid signature length)"
So something seems to be broken with the chainId implementation.

When I try my code in #13 without the chainID, the signature length is correct, but I'm not sure if leaving the chainID out is going to lead to problems? (EDIT: the signature is still invalid, see #16)

EIP720Doman.toJson should not include outputs for null values of salt

I am hitting a compatibility issue migrating from v.0.0.5 to v0.0.6 since I do not require a salt value in my EIP720Domain. Setting the required salt value to null does not work.

I found if I omitted the salt: null output in the toJson method the downstream libraries reverted to the prior V0.0.5 behavior.

There is likely a more null aware operator way to code this, but here is the logic:

Map<String, dynamic> toJson() {
    if (salt != null) {
      return <String, dynamic>{
        'name': name,
        'version': version,
        'chainId': chainId,
        'salt': salt,
        'verifyingContract': verifyingContract
      };
    }
    else {
      // Omit the null salt entry
      return
        <String, dynamic>{
          'name': name,
          'version': version,
          'chainId': chainId,
          'verifyingContract': verifyingContract
        };
    } 

signMessage do not use privateKeyInBytes when calling SignatureUtil.sign

I want to use EthSigUtil.signMessage using privateKeyInBytes parameter but, in the source code, it's not used when calling SignatureUtil.sign.

Source code:

  static String signMessage(
      {String? privateKey,
      Uint8List? privateKeyInBytes,
      required Uint8List message}) {
    return SignatureUtil.sign(message: message, privateKey: privateKey);
  }

Edit: After looking at the source code of many functions, a looooot of them are not using privateKeyInBytes.

"Error: Exception: Could not construct a recoverable key. This should never happen"

This package doesn't work with messages that have several strings (large messages), most possible due to dart uses UTF-16.
It's limited in the practical usability, unless there is a example, that can assist with this. I tried several.

I have tried to use the other method it provides, which is the signTypedData V1 version, and that works. However the EthSigUtil.ecRecover method to verify and get public address, doesn't support that [signedTypeData].
So for verification/get public address, isn't possible. It would be great if it did, as it would stop this issue.

Hope, I can get assistance with this, thanks.

Transaction could not be decoded

I'm attempting to use the transferWithAuthorization function of USDC. I'm able to sign the typedData but when submitting it with web3.eth.sendSignedTransaction I get the following error:

transaction could not be decoded: could not decode RLP components: insufficient remaining input for short list
or sometimes
transaction could not be decoded: could not decode RLP components: extra data at end

Here is what I use to construct the typedData:

final Map<String, dynamic> rawTypedData = {
      "types": {
        "EIP712Domain": [
          {"name": "name", "type": "string"},
          {"name": "version", "type": "string"},
          {"name": "chainId", "type": "uint256"},
          {"name": "verifyingContract", "type": "address"}
        ],
        "TransferWithAuthorization": [
          {"name": "from", "type": "address"},
          {"name": "to", "type": "address"},
          {"name": "value", "type": "uint256"},
          {"name": "validAfter", "type": "uint256"},
          {"name": "validBefore", "type": "uint256"},
          {"name": "nonce", "type": "bytes32"}
        ]
      },
      "domain": {
        "name": "USDC",
        "version": "2",
        "chainId": config.chain.chainId,
        "verifyingContract": config.chain.usdcContract
      },
      "primaryType": "TransferWithAuthorization",
      "message": {
        "from": user.pubKey,
        "to": ethAddress.toString(),
        "value": amount.toString(),
        "validAfter": BigInt.zero.toString(),
        "validBefore": BigInt.from(9223372036854775807).toString(),
        "nonce": "0x" + Nonce.secure(32).toString()
      }
    };

And I sign it with:

String signedData = EthSigUtil.signTypedData(
          privateKey: bytesToHex(wallet.privateKey.privateKey),
          jsonData: jsonEncode(rawTypedData),
          version: TypedDataVersion.V4);

Finding it hard to debug this, not sure what the error message refers to, or if it's even accurate (the tiniest change in the typedData seems to give slightly different errors)

The print of rawTypedData.toString() is:

{
        types: {
            EIP712Domain: [
              {name: name, type: string}, 
              {name: version, type: string}, 
              {name: chainId, type: uint256}, 
              {name: verifyingContract, type: address}], 
            TransferWithAuthorization: [
              {name: from, type: address}, 
              {name: to, type: address}, 
              {name: value, type: uint256}, 
              {name: validAfter, type: uint256}, 
              {name: validBefore, type: uint256}, 
              {name: nonce, type: bytes32}]
        }, 
        domain: {
            name: USDC, 
            version: 2, 
            chainId: 3, 
            verifyingContract: 0x07865c6e87b9f70255377e024ace6630c1eaa37f
        }, 
        primaryType: TransferWithAuthorization, 
        message: {
                from: 0xfe55e0a42c29d4502631b9123ba585430e1f9cdc, 
                to: 0x33eecb4a75c9241eea0190e5dcdfb76d2ed67613, 
                value: 1000000, 
                validAfter: 0, 
                validBefore: 9223372036854775807, 
                nonce: 0x0f8Vf33cD9ZaLGgZi6c68SbDC5fC5s9xenmiNF8M3H3D20SgWFe3Y8Yqt8m4sJ2w
            }
}

Verifying fails for 1% of cases.

I am using EthSigUtil.signPersonalMessage and EthSigUtil.recoverPersonalSignature

I am importing the following libraries

import 'package:web3dart/web3dart.dart';
import 'package:eth_sig_util/eth_sig_util.dart';
import 'package:collection/collection.dart';
import 'package:web3dart/crypto.dart';
Following is the code for generating the KeyPair. I am using the package:web3dart/web3dart.dart for generating the KeyPairs

                var random_number = Random.secure();
                EthPrivateKey keyPair = EthPrivateKey.createRandom(random_number);

I ran the signing and verifying multiple times in a loop.

When I run over 100 times, I get 1-2 verifications which fail. And this error rate is proportional when I run it over 1000 times too..Roughly 1-2% verification failures. I get Invalid argument(s): invalid signature error

This is my signing logic

     Future<String> sign (final String message) async
    {
            List<int>       message_list   = message.codeUnits;

            final Uint8List bytes_message  = Uint8List
                                                .fromList(message_list);

            String signature               = EthSigUtil.signPersonalMessage
                                                ( 
                                                    privateKey: bytesToHex(keyPair.privateKey), 
                                                    message: bytes_message
                                                );

            return signature;

    }

And the code for verify is this :

Future verify (final String message, final String signature, String public_key) async
{
String recovered_address = '';

            List<int> message_list   = message.codeUnits;

            final Uint8List bytes_message  = Uint8List
                                                .fromList(message_list);

            try {

            recovered_address            = EthSigUtil.recoverPersonalSignature
                                                    (
                                                        signature: signature, 
                                                        message: bytes_message
                                                    );
            }
            catch (e) 
                  {
                        return false;
                  }
            var given_address = publicKeyToAddress(hexToBytes(public_key));

            bool is_verified = const ListEquality()
                            .equals(
                                        hexToBytes(recovered_address), 
                                        given_address
                                    );
            return is_verified;
    }

Am I doing something wrong?

Signature not matching metamask

I am not seeing the results I expect when I compare signature request signed by metamask and the plugin. Here is a failing unit test with example data, how I am using it, and the result I expect.

Thank you for your time on this!

import 'dart:convert';

import 'package:eth_sig_util/eth_sig_util.dart';
import 'package:eth_sig_util/model/typed_data.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  JsonEncoder encoder = JsonEncoder.withIndent('  ');
  String? prettyprint;

  // Keys for unit testing only
  String walletAddress = '0xbdB75073F7bC2E2fe26F846975b3ff64fd30D3b4';
  String walletPrivateKey =
      'dcb9f84b32289b5079d58d0c8231d10e8c8cef7034493a91aa1b185068fdd6c8';

  // // Create lazyMintRequestBody part 1
  Map<String, dynamic> messageToSign = <String, dynamic>{
    "@type": "ERC721",
    "contract": "0xB0EA149212Eb707a1E5FC1D2d3fD318a8d94cf05",
    "tokenId":
        "85811016661282950678352305265629525770441762754136673725069232823650475835400",
    "uri": "/ipfs/QmVUzkLxEoCRyit8uXAuUoVUgFw1c7Uvz7T4bkGgJUwxcf",
    "creators": [
      {"account": walletAddress, "value": 10000}
    ],
    "royalties": <int>[],
    "tokenURI": "/ipfs/QmVUzkLxEoCRyit8uXAuUoVUgFw1c7Uvz7T4bkGgJUwxcf",
  };

  prettyprint = encoder.convert(messageToSign);
  //print('messageToSign---\n$prettyprint\n---');

  final TypedMessage rawTypedData = TypedMessage(
    types: {
      "EIP712Domain": [
        TypedDataField(name: "name", type: "string"),
        TypedDataField(name: "version", type: "string"),
        TypedDataField(name: "chainId", type: "uint256"),
        TypedDataField(name: "verifyingContract", type: "address")
      ],
      "Mint721": [
        TypedDataField(name: "tokenId", type: "uint256"),
        TypedDataField(name: "tokenURI", type: "string"),
        TypedDataField(name: "uri", type: "string"),
        TypedDataField(name: "creators", type: "Part[]"),
        TypedDataField(name: "royalties", type: "Part[]")
      ],
      "Part": [
        TypedDataField(name: "account", type: "address"),
        TypedDataField(name: "value", type: "uint96"),
      ]
    },
    domain: EIP712Domain(
        name: "Mint721",
        version: "1",
        chainId: 3,
        verifyingContract: "0xB0EA149212Eb707a1E5FC1D2d3fD318a8d94cf05"),
    primaryType: "Mint721",
    message: messageToSign,
  );

  prettyprint = encoder.convert(rawTypedData);
  print('rawTypedData---\n$prettyprint\n---');

  /// Sign the typed Data Structure of request
  String jsonData = jsonEncode(rawTypedData);

  String signature = '';

  test('test signature value of typed data', () {
    signature = EthSigUtil.signTypedData(
        privateKey: walletPrivateKey,
        jsonData: jsonData,
        version: TypedDataVersion.V4,
        chainId: 3);
    expect(signature,
        '0xa275d9322e77f0b9680393028363d6d5ede89149e2e1c2931cfbc318ddc1496b7cee8bee4dbd632d859ebdd0bd7f2343ddcd5c2b2768b3c512963c49f1800fe11c');
  });
}

// from = "0xbdB75073F7bC2E2fe26F846975b3ff64fd30D3b4"
// SignedDataRequest (msgData)
//{"types":{"EIP712Domain":[{"type":"string","name":"name"},{"type":"string","name":"version"},{"type":"uint256","name":"chainId"},{"type":"address","name":"verifyingContract"}],"Part":[{"name":"account","type":"address"},{"name":"value","type":"uint96"}],"Mint721":[{"name":"tokenId","type":"uint256"},{"name":"tokenURI","type":"string"},{"name":"uri","type":"string"},{"name":"creators","type":"Part[]"},{"name":"royalties","type":"Part[]"}]},"domain":{"name":"Mint721","version":"1","chainId":3,"verifyingContract":"0xB0EA149212Eb707a1E5FC1D2d3fD318a8d94cf05"},"primaryType":"Mint721","message":{"@type":"ERC721","contract":"0xB0EA149212Eb707a1E5FC1D2d3fD318a8d94cf05","tokenId":"85811016661282950678352305265629525770441762754136673725069232823650475835400","uri":"/ipfs/QmVUzkLxEoCRyit8uXAuUoVUgFw1c7Uvz7T4bkGgJUwxcf","creators":[{"account":"0xbdB75073F7bC2E2fe26F846975b3ff64fd30D3b4","value":10000}],"royalties":[],"tokenURI":"/ipfs/QmVUzkLxEoCRyit8uXAuUoVUgFw1c7Uvz7T4bkGgJUwxcf"}}
//  const sig = await provider.send("eth_signTypedData_v4", [from, msgData]);
// Provider returned
// sig : 0xa275d9322e77f0b9680393028363d6d5ede89149e2e1c2931cfbc318ddc1496b7cee8bee4dbd632d859ebdd0bd7f2343ddcd5c2b2768b3c512963c49f1800fe11c
// r: 0xa275d9322e77f0b9680393028363d6d5ede89149e2e1c2931cfbc318ddc1496b , s:  0x7cee8bee4dbd632d859ebdd0bd7f2343ddcd5c2b2768b3c512963c49f1800fe1 , v: 28

Encode error

Hi,
I have a issue when i try to encode bool type with solidityPack method. I tried to dig out on the source code and found that issue.
I've created this (PR) that works for me right now,

Please kindly review!

Invalid signature / v value

I'm attempting to use USDC's transferWithAuthorization on a Dart client for submission by a Node.js backend.

My understanding of the flow so far:

  1. Create typedData
  2. Sign typedData using etc-sig-util
  3. Create ethereum transaction calling USDC transferWithAuthorization
  4. Sign transaction using web3dart
  5. Send signed transaction to backend
  6. Backend submits the signed transaction

I am currently stuck on step 4, where ethClient.signTransaction gives the following error:
RPCError: got code 3 with msg "execution reverted: ECRecover: invalid signature 'v' value".

v is from sigParams.v, but cast to a BigInt as otherwise the Web3Dart.Transaction.callContract threw a type error.

Any help figuring out the flow and getting this to work would be appreciated.

Full code:

Future<String?> signUSDC(BigInt amount, Web3Dart.EthereumAddress ethAddress, User user) async {
    final config = ref.read(configurationProvider).instance;
    final wallet =
        Web3Dart.Wallet.fromJson(user.ethereumWallet!, kWalletPassword);

    final validAfter = BigInt.zero;
    final validBefore = BigInt.from(9223372036854775807);
    final nonce = Nonce.secure(32);
    final nonceBytes = utf8.encode(nonce.toString());

    // 1. Create typed data
    final Map<String, dynamic> rawTypedData = {
      "types": {
        "EIP712Domain": [
          {"name": "name", "type": "string"},
          {"name": "version", "type": "string"},
          {"name": "chainId", "type": "uint256"},
          {"name": "verifyingContract", "type": "address"}
        ],
        "TransferWithAuthorization": [
          {"name": "from", "type": "address"},
          {"name": "to", "type": "address"},
          {"name": "value", "type": "uint256"},
          {"name": "validAfter", "type": "uint256"},
          {"name": "validBefore", "type": "uint256"},
          {"name": "nonce", "type": "bytes32"}
        ]
      },
      "domain": {
        "name": "USDC",
        "version": "2",
        "chainId": config.chain.chainId,
        "verifyingContract": config.chain.usdcContract
      },
      "primaryType": "TransferWithAuthorization",
      "message": {
        "from": user.pubKey,
        "to": ethAddress.toString(),
        "value": amount.toInt(),
        "validAfter": validAfter.toInt(),
        "validBefore": validBefore.toInt(),
        "nonce": nonceBytes.toString()
      }
    };

    // 2. Sign typed data
    String signature = EthSigUtil.signTypedData(
        privateKey: bytesToHex(wallet.privateKey.privateKey),
        jsonData: jsonEncode(rawTypedData),
        version: TypedDataVersion.V4,
        chainId: config.chain.chainId);

    final contract = await ref.read(usdcContractProvider.future);
    var sigParams = SignatureUtil.fromRpcSig(signature);

    // 3. Create transaction calling 'transferWithAuthorization'
    final transaction = Web3Dart.Transaction.callContract(
      contract: contract,
      function: contract.function('transferWithAuthorization'),
      parameters: [
        Web3Dart.EthereumAddress.fromHex(user.pubKey!),
        ethAddress,
        amount,
        validAfter,
        validBefore,
        nonceBytes,
        BigInt.from(sigParams.v),
        bigIntToUint8List(sigParams.r),
        bigIntToUint8List(sigParams.s)
      ],
    );

    // 4. Sign transaction
    final signedTx = await ethClient.signTransaction(
        wallet.privateKey, 
        transaction,
        chainId: config.chain.chainId, 
        fetchChainIdFromNetworkId: false);
    final hexTx = "0x" + hex.encode(signedTx); // not sure if signedTx or hexTx should be used

    // 5. submit signed transaction to backend, get hash in return
    try {
      final body = json.encode((await defaultParams)
        ..addAll({
          "serializedTx": signedTx,
          "validationCode": "[redacted]"
        }));

      return sendRequest(baseUrl.asUri / '[redacted_endpoint]',
          method: DataRequestMethod.POST,
          body: body,
          omitDefaultParams: false, onSuccess: (map) {
        return map['hash'] as String;
      }, onError: (error) {
        return null;
      });
    } catch (error) {
      return null;
    }
  }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.