addSignatureToExtrinsic static method

Uint8List addSignatureToExtrinsic({
  1. required Uint8List publicKey,
  2. required String hexSignature,
  3. required Map<String, dynamic> payload,
})

Implementation

static Uint8List addSignatureToExtrinsic({
  required Uint8List publicKey,
  required String hexSignature,
  required Map<String, dynamic> payload,
}) {
  final method = payload['method'] is Uint8List
      ? (payload['method'] as Uint8List).toList()
      : hex.decode(_normalizeHex(payload['method']));
  final signature = hex.decode(_normalizeHex(hexSignature));

  const signedFlag = 0x80; // For signed extrinsics
  final versionValue = payload['version']?.toString() ?? '4';
  final version = int.parse(versionValue);
  // Extrinsic version = signed flag + version
  final int extrinsicVersion = signedFlag | version; // 0x80 + 0x04 = 0x84

  // Detect signature type by evaluating the address if possible, default to Sr25519
  final ss58Address = payload['address']?.toString() ?? '';
  final signatureType = _guessSignatureTypeFromAddress(ss58Address);

  // Era
  final eraValue = _normalizeHex(payload['era']);
  List<int> eraBytes;
  if (eraValue == '00') {
    eraBytes = [0x00];
  } else {
    eraBytes = hex.decode(eraValue);
    if (eraBytes.length != 2) {
      throw ArgumentError('Mortal era must be 2 bytes, got 0x$eraValue');
    }
  }

  // Nonce
  final nonceValue = _parseHex(payload['nonce']);
  final nonceBytes = [
    nonceValue & 0xFF,
    (nonceValue >> 8) & 0xFF,
  ];

  final tipValue = BigInt.parse(_normalizeHex(payload['tip']), radix: 16);
  final tipBytes = _compactEncodeBigInt(tipValue);

  final extrinsicBody = BytesBuilder();
  extrinsicBody.addByte(0x00); // MultiAddress::Id
  extrinsicBody.add(publicKey);
  extrinsicBody.addByte(signatureType);
  extrinsicBody.add(signature);
  extrinsicBody.add(eraBytes);
  extrinsicBody.add(nonceBytes);
  extrinsicBody.add(tipBytes);
  extrinsicBody.add(method);

  final bodyBytes = extrinsicBody.toBytes();

  final lengthPrefix = _compactEncodeInt(
    bodyBytes.length + 1, // +1 for version byte
  );

  final full = BytesBuilder();
  full.add(lengthPrefix);
  full.addByte(extrinsicVersion);
  full.add(bodyBytes);

  return full.toBytes();
}