approveSession method

  1. @override
Future<ApproveResponse> approveSession({
  1. required int id,
  2. required Map<String, Namespace> namespaces,
  3. Map<String, String>? sessionProperties,
  4. String? relayProtocol,
})
override

Approves a proposal with the id provided in the parameters. Assumes the proposal is already created.

Implementation

@override
Future<ApproveResponse> approveSession({
  required int id,
  required Map<String, Namespace> namespaces,
  Map<String, String>? sessionProperties,
  String? relayProtocol,
}) async {
  // print('sign approveSession');
  _checkInitialized();
  _confirmOnlineStateOrThrow();

  await _isValidApprove(
    id: id,
    namespaces: namespaces,
    sessionProperties: sessionProperties,
    relayProtocol: relayProtocol,
  );

  final ProposalData proposal = proposals.get(
    id.toString(),
  )!;

  final String selfPubKey = await core.crypto.generateKeyPair();
  final String peerPubKey = proposal.proposer.publicKey;
  final String sessionTopic = await core.crypto.generateSharedKey(
    selfPubKey,
    peerPubKey,
  );
  // print('approve session topic: $sessionTopic');
  final protocol =
      relayProtocol ?? WalletConnectConstants.RELAYER_DEFAULT_PROTOCOL;
  final relay = Relay(protocol);

  // Respond to the proposal
  await core.pairing.sendResult(
    id,
    proposal.pairingTopic,
    MethodConstants.WC_SESSION_PROPOSE,
    WcSessionProposeResponse(
      relay: relay,
      responderPublicKey: selfPubKey,
    ),
  );
  await _deleteProposal(id);
  await core.pairing.activate(topic: proposal.pairingTopic);

  await core.pairing.updateMetadata(
    topic: proposal.pairingTopic,
    metadata: proposal.proposer.metadata,
  );

  await core.relayClient.subscribe(topic: sessionTopic);

  final int expiry = WalletConnectUtils.calculateExpiry(
    WalletConnectConstants.SEVEN_DAYS,
  );

  SessionData session = SessionData(
    topic: sessionTopic,
    pairingTopic: proposal.pairingTopic,
    relay: relay,
    expiry: expiry,
    acknowledged: false,
    controller: selfPubKey,
    namespaces: namespaces,
    self: ConnectionMetadata(
      publicKey: selfPubKey,
      metadata: metadata,
    ),
    peer: proposal.proposer,
    sessionProperties: proposal.sessionProperties,
    transportType: TransportType.relay,
  );

  onSessionConnect.broadcast(SessionConnect(session));

  await sessions.set(sessionTopic, session);
  await _setSessionExpiry(sessionTopic, expiry);

  // `wc_sessionSettle` is not critical throughout the entire session.
  final settleRequest = WcSessionSettleRequest(
    relay: relay,
    namespaces: namespaces,
    sessionProperties: sessionProperties,
    expiry: expiry,
    controller: ConnectionMetadata(
      publicKey: selfPubKey,
      metadata: metadata,
    ),
  );
  bool acknowledged = await core.pairing
      .sendRequest(
        sessionTopic,
        MethodConstants.WC_SESSION_SETTLE,
        settleRequest.toJson(),
      )
      // Sometimes we don't receive any response for a long time,
      // in which case we manually time out to prevent waiting indefinitely.
      .timeout(const Duration(seconds: 15))
      .catchError(
    (_) {
      return false;
    },
  );

  session = session.copyWith(
    acknowledged: acknowledged,
  );

  if (acknowledged && sessions.has(sessionTopic)) {
    // We directly update the latest value.
    await sessions.set(
      sessionTopic,
      session,
    );
  }

  return ApproveResponse(
    topic: sessionTopic,
    session: session,
  );
}