approveSessionAuthenticate method

  1. @override
Future<ApproveResponse> approveSessionAuthenticate({
  1. required int id,
  2. List<Cacao>? auths,
})
override

Implementation

@override
Future<ApproveResponse> approveSessionAuthenticate({
  required int id,
  List<Cacao>? auths,
}) async {
  _checkInitialized();

  final pendingSessionAuthRequests = getPendingSessionAuthRequests();

  if (!pendingSessionAuthRequests.containsKey(id)) {
    throw Errors.getInternalError(
      Errors.MISSING_OR_INVALID,
      context: 'approveSessionAuthenticate() '
          'Could not find pending auth request with id $id',
    ).toSignError();
  }

  AuthApiValidators.isValidRespondAuthenticate(
    id: id,
    pendingRequests: pendingSessionAuthRequests,
    auths: auths,
  );

  final pendingRequest = pendingSessionAuthRequests[id]!;
  if (!pendingRequest.transportType.isLinkMode) {
    _confirmOnlineStateOrThrow();
  }

  final receiverPublicKey = pendingRequest.requester.publicKey;
  final senderPublicKey = await core.crypto.generateKeyPair();
  final responseTopic = core.crypto.getUtils().hashKey(receiverPublicKey);

  final encodeOpts = EncodeOptions(
    type: EncodeOptions.TYPE_1,
    receiverPublicKey: receiverPublicKey,
    senderPublicKey: senderPublicKey,
  );

  final approvedMethods = <String>{};
  final approvedAccounts = <String>{};
  for (final Cacao cacao in auths!) {
    final isValid = await validateSignedCacao(
      cacao: cacao,
      projectId: core.projectId,
    );
    if (!isValid) {
      final error = Errors.getSdkError(
        Errors.SIGNATURE_VERIFICATION_FAILED,
        context: 'Signature verification failed',
      ).toSignError();
      await core.pairing.sendError(
        id,
        responseTopic,
        MethodConstants.WC_SESSION_AUTHENTICATE,
        JsonRpcError(code: error.code, message: error.message),
        encodeOptions: encodeOpts,
      );
      throw error;
    }

    final CacaoPayload payload = cacao.p;
    final chainId = AddressUtils.getDidChainId(payload.iss);
    final approvedChains = ['eip155:$chainId'];

    final recap = ReCapsUtils.getRecapFromResources(
      resources: payload.resources,
    );
    if (recap != null) {
      final methodsfromRecap = ReCapsUtils.getMethodsFromRecap(recap);
      final chainsFromRecap = ReCapsUtils.getChainsFromRecap(recap);
      approvedMethods.addAll(methodsfromRecap);
      approvedChains.addAll(chainsFromRecap);
    }

    final parsedAddress = AddressUtils.getDidAddress(payload.iss);
    for (var chain in approvedChains.toSet()) {
      approvedAccounts.add('$chain:${parsedAddress.toEIP55()}');
    }
  }

  final sessionTopic = await core.crypto.generateSharedKey(
    senderPublicKey,
    receiverPublicKey,
  );

  SessionData? session;
  if (approvedMethods.isNotEmpty) {
    session = SessionData(
      topic: sessionTopic,
      acknowledged: true,
      self: ConnectionMetadata(
        publicKey: senderPublicKey,
        metadata: metadata,
      ),
      peer: pendingRequest.requester,
      controller: receiverPublicKey,
      expiry: ReownCoreUtils.calculateExpiry(
        ReownConstants.SEVEN_DAYS,
      ),
      relay: Relay(ReownConstants.RELAYER_DEFAULT_PROTOCOL),
      pairingTopic: pendingRequest.pairingTopic,
      namespaces: NamespaceUtils.buildNamespacesFromAuth(
        accounts: approvedAccounts,
        methods: approvedMethods,
      ),
      authentication: auths,
      transportType: pendingRequest.transportType,
    );

    await core.relayClient.subscribe(topic: sessionTopic);
    await sessions.set(sessionTopic, session);
    await core.pairing.updateMetadata(
      topic: pendingRequest.pairingTopic,
      metadata: pendingRequest.requester.metadata,
    );
  }

  await sessionAuthRequests.delete(id.toString());
  await core.pairing.activate(topic: pendingRequest.pairingTopic);

  final result = WcSessionAuthRequestResult(
    cacaos: auths,
    responder: ConnectionMetadata(
      publicKey: senderPublicKey,
      metadata: metadata,
    ),
  );
  await core.pairing.sendResult(
    id,
    responseTopic,
    MethodConstants.WC_SESSION_AUTHENTICATE,
    result.toJson(),
    encodeOptions: encodeOpts,
    appLink: _getAppLinkIfEnabled(pendingRequest.requester.metadata),
  );

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