solana_kit_mobile_wallet_adapter_protocol 0.5.1 copy "solana_kit_mobile_wallet_adapter_protocol: ^0.5.1" to clipboard
solana_kit_mobile_wallet_adapter_protocol: ^0.5.1 copied to clipboard

Pure Dart implementation of the Solana Mobile Wallet Adapter protocol v2.0. Provides cryptography, message framing, JSON-RPC types, and session management without Flutter dependencies.

solana_kit_mobile_wallet_adapter_protocol #

pub package docs website CI coverage

Pure Dart implementation of the Solana Mobile Wallet Adapter v2.0 protocol. It handles P-256 cryptography, session handshakes, encrypted message framing, JSON-RPC request/response encoding, association URI building/parsing, and protocol version negotiation.

The package has zero Flutter dependency and runs in server-side Dart, CLI tools, or any Dart environment.

What it covers #

  • P-256 ECDSA/ECDH cryptography via pointycastle (pure Dart, cross-platform)
  • AES-128-GCM encryption with sequence number AAD for replay attack prevention
  • HKDF-SHA256 key derivation with association public key as salt
  • HELLO_REQ / HELLO_RSP handshake for session establishment
  • JSON-RPC 2.0 message encryption/decryption
  • Association URI building and parsing (local + remote)
  • Wallet proxy with v1/legacy backwards compatibility
  • Sign In With Solana (SIWS) message builder following EIP-4361
  • JWS ES256 compact serialization for attestation
  • Central error codes integrated with solana_kit_errors

Installation #

Install the package directly:

dependencies:
  "solana_kit_mobile_wallet_adapter_protocol": ^0.5.1

If your app uses several Solana Kit packages together, you can also depend on the umbrella package instead:

dart pub add solana_kit

Inside this monorepo, Dart workspace resolution uses the local package automatically.

Documentation #

For architecture notes, getting-started guides, and cross-package examples, start with the workspace docs site and then drill down into the package README and API reference.

Usage #

Association keypair generation #

import 'package:solana_kit_mobile_wallet_adapter_protocol/solana_kit_mobile_wallet_adapter_protocol.dart';

void main() {
  // Generate keypairs for a new session.
  final associationKeypair = generateAssociationKeypair();
  final ecdhKeypair = generateEcdhKeypair();

  // Get the association token (base64url-encoded public key).
  final token = getAssociationToken(associationKeypair.publicKey);

  print(token);
  print(ecdhKeypair.publicKey);
}

Building association URIs #

import 'dart:typed_data';

import 'package:solana_kit_mobile_wallet_adapter_protocol/solana_kit_mobile_wallet_adapter_protocol.dart';

void main() {
  final associationKeypair = generateAssociationKeypair();

  // Local association (same-device).
  final uri = buildLocalAssociationUri(
    associationKeypair.publicKey,
    55123,
  );
  // -> solana-wallet:/v1/associate/local?association=...&port=55123

  // Remote association (via reflector).
  final reflectorId = Uint8List.fromList([1, 2, 3]);
  final remoteUri = buildRemoteAssociationUri(
    associationKeypair.publicKey,
    'reflect.example.com',
    reflectorId,
  );

  print(uri);
  print(remoteUri);
}

HELLO handshake #

import 'dart:typed_data';

import 'package:solana_kit_mobile_wallet_adapter_protocol/solana_kit_mobile_wallet_adapter_protocol.dart';

void main() {
  final associationKeypair = generateAssociationKeypair();
  final ecdhKeypair = generateEcdhKeypair();

  // Create HELLO_REQ (129 bytes: 65B ECDH pubkey + 64B ECDSA signature).
  final helloReq = createHelloReq(ecdhKeypair, associationKeypair);

  // Parse HELLO_RSP from the wallet.
  final helloRspBytes = Uint8List(129);
  final result = parseHelloRsp(helloRspBytes, associationKeypair, ecdhKeypair);
  final sharedSecret = result.sharedSecret; // 16-byte AES key

  print(helloReq.length);
  print(sharedSecret);
}

Encrypted messaging #

import 'dart:typed_data';

import 'package:solana_kit_mobile_wallet_adapter_protocol/solana_kit_mobile_wallet_adapter_protocol.dart';

void main() {
  final sharedSecret = Uint8List(16);

  // Encrypt a JSON-RPC request.
  final encrypted = encryptJsonRpcRequest(
    1, // sequence number
    'authorize',
    {'chain': 'solana:mainnet'},
    sharedSecret,
  );

  // Decrypt a JSON-RPC response.
  final encryptedBytes = Uint8List(0);
  final response = decryptJsonRpcResponse(encryptedBytes, sharedSecret);

  print(encrypted);
  print(response);
}

Wallet proxy #

import 'package:solana_kit_mobile_wallet_adapter_protocol/solana_kit_mobile_wallet_adapter_protocol.dart';

Future<void> main() async {
  // Create a wallet proxy that handles v1/legacy compatibility.
  final sendRequest = (String method, Map<String, Object?> params) async {
    return <String, Object?>{};
  };
  final sessionProps = const SessionProperties(
    protocolVersion: ProtocolVersion.v1,
  );
  final wallet = createMobileWalletProxy(sendRequest, sessionProps);

  final authResult = await wallet.authorize({
    'identity': {'name': 'My dApp'},
    'chain': 'solana:mainnet',
  });

  print(authResult);
}

Protocol details #

Wire format #

Each encrypted message follows this binary format:

[4B sequence number (big-endian)] [12B random IV] [ciphertext + 16B GCM tag]

The 4-byte sequence number is also used as AAD (Additional Authenticated Data) for AES-GCM, preventing replay attacks.

Handshake flow #

  1. dApp generates association keypair (P-256 ECDSA) and ECDH keypair (P-256)
  2. dApp sends HELLO_REQ: [65B ECDH pubkey][64B ECDSA signature]
  3. Wallet sends HELLO_RSP: [65B wallet ECDH pubkey][optional encrypted session props]
  4. Both sides derive shared secret via ECDH + HKDF-SHA256 -> 16-byte AES key
  5. All subsequent messages use AES-128-GCM with incrementing sequence numbers

Protocol versions #

  • v1: Uses chain identifiers (solana:mainnet, solana:devnet, solana:testnet), feature arrays, and separate reauthorize method
  • legacy: Uses cluster names (mainnet-beta, devnet, testnet), boolean feature flags (supports_sign_and_send_transactions), and authorize with auth_token for reauthorization

Example #

Use example/main.dart as a runnable starting point for solana_kit_mobile_wallet_adapter_protocol.

  • Import path: package:solana_kit_mobile_wallet_adapter_protocol/solana_kit_mobile_wallet_adapter_protocol.dart
  • This section is centrally maintained with mdt to keep package guidance aligned.
  • After updating shared docs templates, run docs:update from the repo root.

Maintenance #

  • Validate docs in CI and locally with docs:check.
  • Keep examples focused on one workflow and reference package README sections for deeper API details.
0
likes
0
points
1.99k
downloads

Publisher

unverified uploader

Weekly Downloads

Pure Dart implementation of the Solana Mobile Wallet Adapter protocol v2.0. Provides cryptography, message framing, JSON-RPC types, and session management without Flutter dependencies.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

pointycastle, solana_kit_codecs_strings, solana_kit_errors

More

Packages that depend on solana_kit_mobile_wallet_adapter_protocol