Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fiat topup setup #118

Merged
merged 5 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 91 additions & 16 deletions crow/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use graphql::perro::{ensure, permanent_failure};
use graphql::schema::list_uncompleted_topups::{topup_status_enum, ListUncompletedTopupsTopup};
use graphql::schema::{
hide_topup, list_uncompleted_topups, register_notification_token, register_topup, HideTopup,
ListUncompletedTopups, RegisterNotificationToken, RegisterTopup,
complete_topup_setup, hide_topup, list_uncompleted_topups, register_notification_token,
start_topup_setup, CompleteTopupSetup, HideTopup, ListUncompletedTopups,
RegisterNotificationToken, StartTopupSetup,
};
use graphql::{build_client, parse_from_rfc3339, post_blocking, ExchangeRate};
use honeybadger::Auth;
use std::sync::Arc;
use std::time::SystemTime;

use graphql::perro::runtime_error;
use graphql::schema::complete_topup_setup::CompleteTopupSetupCompleteTopupSetup;
pub use isocountry::CountryCode;
pub use isolanguage_1::LanguageCode;

Expand Down Expand Up @@ -63,6 +65,58 @@ pub struct TopupInfo {
pub error: Option<TopupError>,
}

pub struct FiatTopupSetupChallenge {
pub id: String,
pub challenge: String,
}

/// Information about a fiat top-up registration
#[derive(Debug, Clone, PartialEq)]
pub struct FiatTopupSetupInfo {
pub order_id: String,
/// The user should transfer fiat from this IBAN
pub debitor_iban: String,
/// This reference should be included in the fiat transfer reference
pub creditor_reference: String,
/// The user should transfer fiat to this IBAN
pub creditor_iban: String,
pub creditor_bank_name: String,
pub creditor_bank_street: String,
pub creditor_bank_postal_code: String,
pub creditor_bank_town: String,
pub creditor_bank_country: String,
pub creditor_bank_bic: String,
pub creditor_name: String,
pub creditor_street: String,
pub creditor_postal_code: String,
pub creditor_town: String,
pub creditor_country: String,
pub currency: String,
}

impl From<CompleteTopupSetupCompleteTopupSetup> for FiatTopupSetupInfo {
fn from(value: CompleteTopupSetupCompleteTopupSetup) -> Self {
Self {
order_id: value.id,
debitor_iban: value.debitor_iban,
creditor_reference: value.creditor_reference,
creditor_iban: value.creditor_iban,
creditor_bank_name: value.creditor_bank_name,
creditor_bank_street: value.creditor_bank_street,
creditor_bank_postal_code: value.creditor_bank_postal_code,
creditor_bank_town: value.creditor_bank_town,
creditor_bank_country: value.creditor_bank_country,
creditor_bank_bic: value.creditor_bank_bic,
creditor_name: value.creditor_name,
creditor_street: value.creditor_street,
creditor_postal_code: value.creditor_postal_code,
creditor_town: value.creditor_town,
creditor_country: value.creditor_country,
currency: value.currency,
}
}
}

pub struct OfferManager {
backend_url: String,
auth: Arc<Auth>,
Expand All @@ -73,28 +127,49 @@ impl OfferManager {
Self { backend_url, auth }
}

pub fn register_topup(
pub fn start_topup_setup(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we accommodate for a referral code already?

&self,
order_id: String,
node_pubkey: String,
provider: String,
source_iban: String,
user_currency: String,
email: Option<String>,
referral_code: Option<String>,
) -> graphql::Result<()> {
let variables = register_topup::Variables {
order_id,
) -> graphql::Result<FiatTopupSetupChallenge> {
let variables = start_topup_setup::Variables {
email,
node_pubkey,
provider,
referral_code,
source_iban,
user_currency,
};
let access_token = self.auth.query_token()?;
let client = build_client(Some(&access_token))?;
let data = post_blocking::<RegisterTopup>(&client, &self.backend_url, variables)?;
ensure!(
matches!(
data.register_topup,
Some(register_topup::RegisterTopupRegisterTopup { .. })
),
permanent_failure("Backend rejected topup registration")
);
Ok(())
let data = post_blocking::<StartTopupSetup>(&client, &self.backend_url, variables)?;

Ok(FiatTopupSetupChallenge {
id: data.start_topup_setup.id,
challenge: data.start_topup_setup.challenge,
})
}

pub fn complete_topup_setup(
&self,
id: String,
signed_challenge: String,
source_iban: String,
) -> graphql::Result<FiatTopupSetupInfo> {
let variables = complete_topup_setup::Variables {
id,
signed_challenge,
source_iban,
};
let access_token = self.auth.query_token()?;
let client = build_client(Some(&access_token))?;
let data = post_blocking::<CompleteTopupSetup>(&client, &self.backend_url, variables)?;

Ok(data.complete_topup_setup.into())
}

pub fn register_notification_token(
Expand Down
28 changes: 28 additions & 0 deletions graphql/schemas/operations.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,31 @@ mutation DisableLightningAddresses($addresses: [String!]!) {
mutation EnableLightningAddresses($addresses: [String!]!) {
enable_lightning_addresses(addresses: $addresses)
}

mutation StartTopupSetup($email: String, $node_pubkey: String!, $provider: String!, $referralCode: String, $source_iban: String!, $user_currency: String!) {
start_topup_setup(email: $email, node_pubkey: $node_pubkey, provider: $provider, referralCode: $referralCode, source_iban: $source_iban, user_currency: $user_currency) {
id
challenge
}
}

mutation CompleteTopupSetup($id: String!, $signedChallenge: String!, $sourceIban: String!) {
complete_topup_setup(id: $id, signed_challenge: $signedChallenge, source_iban: $sourceIban) {
id
debitorIban
creditorReference
creditorIban
creditorBankName
creditorBankStreet
creditorBankPostalCode
creditorBankTown
creditorBankCountry
creditorBankBic
creditorName
creditorStreet
creditorPostalCode
creditorTown
creditorCountry
currency
}
}
113 changes: 36 additions & 77 deletions graphql/schemas/schema_wallet_read.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,25 @@ enum ChallengeSignatureType {
SECP256K1
}

type CompleteTopupSetupResponse {
creditorBankBic: String!
creditorBankCountry: String!
creditorBankName: String!
creditorBankPostalCode: String!
creditorBankStreet: String!
creditorBankTown: String!
creditorCountry: String!
creditorIban: String!
creditorName: String!
creditorPostalCode: String!
creditorReference: String!
creditorStreet: String!
creditorTown: String!
currency: String!
debitorIban: String!
id: String!
}

type CreateBackupResponse {
schemaName: String
schemaVersion: String
Expand Down Expand Up @@ -199,6 +218,11 @@ type SessionPermit {
walletPubKeyId: String
}

type StartTopupSetupResponse {
challenge: String!
id: String!
}

"""
Boolean expression to compare columns of type "String". All fields are combined with logical 'AND'.
"""
Expand Down Expand Up @@ -316,7 +340,7 @@ unique or primary key constraints on table "accepted_terms_conditions"
"""
enum accepted_terms_conditions_constraint {
"""
unique or primary key constraint on columns "id", "service"
unique or primary key constraint on columns "service", "id"
"""
accepted_terms_conditions_pkey
}
Expand Down Expand Up @@ -521,26 +545,6 @@ enum country_select_column {
name
}

"""
Streaming cursor of the table "country"
"""
input country_stream_cursor_input {
"""Stream column input with initial value"""
initial_value: country_stream_cursor_value_input!

"""cursor ordering"""
ordering: cursor_ordering
}

"""Initial value of the column from where the streaming should start"""
input country_stream_cursor_value_input {
callingCode: String
countryCode: String
currencyCode: bpchar
currencyName: String
name: String
}

"""
columns and relationships of "currency"
"""
Expand Down Expand Up @@ -697,6 +701,7 @@ type mutation_root {
accept_terms_conditions_v2(args: AcceptTermsConditionsV2Input): AcceptTermsConditionsV2Response
accept_wallet_acl_by_pk(pk_columns: AcceptWalletPkRequestInput!): WalletAcl
assign_lightning_address: LightningAddressResponse
complete_topup_setup(id: String!, signed_challenge: String!, source_iban: String!): CompleteTopupSetupResponse!
create_backup(encryptedBackup: String!, schemaName: String!, schemaVersion: String!): CreateBackupResponse
disable_lightning_addresses(addresses: [String!]!): Void
enable_lightning_addresses(addresses: [String!]!): Void
Expand Down Expand Up @@ -728,13 +733,14 @@ type mutation_root {
refresh_session(refreshToken: String!): TokenContainer
refresh_session_v2(refreshToken: String!): SessionPermit
register_notification_token(language: String!, notificationToken: String!): Token
register_topup(email: String, orderId: String!): RegisterTopupResponse
register_topup(email: String, orderId: String!, referralCode: String): RegisterTopupResponse
report_payment_telemetry(events: PaymentTelemetryEventsInput, telemetryId: String!): ReportPaymentTelemetryResponse
request_phone_number_verification(encryptedNumber: String!, number: String!): Void
start_prepared_session(challenge: String!, challengeSignature: String!, challengeSignatureType: ChallengeSignatureType, preparedPermissionToken: String!): TokenContainer
start_prepared_session_v2(challenge: String!, challengeSignature: String!, challengeSignatureType: ChallengeSignatureType, preparedPermissionToken: String!): SessionPermit
start_session(authPubKey: String!, challenge: String!, challengeSignature: String!, challengeSignatureType: ChallengeSignatureType, signedAuthPubKey: String!, walletPubKey: String!): TokenContainer
start_session_v2(authPubKey: String!, challenge: String!, challengeSignature: String!, challengeSignatureType: ChallengeSignatureType, signedAuthPubKey: String!, walletPubKey: String!): SessionPermit
start_topup_setup(email: String, node_pubkey: String!, provider: String!, referralCode: String, source_iban: String!, user_currency: String!): StartTopupSetupResponse!
submit_lnurl_pay_invoice(id: String!, invoice: String): Void
verify_phone_number(number: String!, otp: String!): Void
}
Expand Down Expand Up @@ -801,9 +807,7 @@ type query_root {
backup_service_version: String
consumer_service_version: String

"""
fetch data from the table: "country"
"""
"""Get information about all countries supported by lipa"""
country(
"""distinct select on columns"""
distinct_on: [country_select_column!]
Expand All @@ -821,12 +825,10 @@ type query_root {
where: country_bool_exp
): [country!]!

"""fetch data from the table: "country" using primary key columns"""
"""Get information about a specific country supported by lipa"""
country_by_pk(countryCode: String!): country

"""
fetch data from the table: "currency"
"""
"""Get exchange rates for all currencies supported by lipa"""
currency(
"""distinct select on columns"""
distinct_on: [currency_select_column!]
Expand All @@ -844,7 +846,7 @@ type query_root {
where: currency_bool_exp
): [currency!]!

"""fetch data from the table: "currency" using primary key columns"""
"""Get exchange rate for a specific currency supported by lipa"""
currency_by_pk(
"""ISO 4217"""
currencyCode: String!
Expand Down Expand Up @@ -878,9 +880,7 @@ type query_root {
prepare_wallet_session(challenge: String!, ownerPubKeyId: String!, signature: String!): String
sms_service_version: String

"""
fetch data from the table: "token"
"""
"""TEST COMMENT"""
token(
"""distinct select on columns"""
distinct_on: [token_select_column!]
Expand Down Expand Up @@ -1001,46 +1001,7 @@ type subscription_root {
where: accepted_terms_conditions_bool_exp
): [accepted_terms_conditions!]!

"""
fetch data from the table: "country"
"""
country(
"""distinct select on columns"""
distinct_on: [country_select_column!]

"""limit the number of rows returned"""
limit: Int

"""skip the first n rows. Use only with order_by"""
offset: Int

"""sort the rows by one or more columns"""
order_by: [country_order_by!]

"""filter the rows returned"""
where: country_bool_exp
): [country!]!

"""fetch data from the table: "country" using primary key columns"""
country_by_pk(countryCode: String!): country

"""
fetch data from the table in a streaming manner: "country"
"""
country_stream(
"""maximum number of rows returned in a single batch"""
batch_size: Int!

"""cursor to stream the results returned by the query"""
cursor: [country_stream_cursor_input]!

"""filter the rows returned"""
where: country_bool_exp
): [country!]!

"""
fetch data from the table: "currency"
"""
"""Get exchange rates for all currencies supported by lipa"""
currency(
"""distinct select on columns"""
distinct_on: [currency_select_column!]
Expand All @@ -1058,7 +1019,7 @@ type subscription_root {
where: currency_bool_exp
): [currency!]!

"""fetch data from the table: "currency" using primary key columns"""
"""Get exchange rate for a specific currency supported by lipa"""
currency_by_pk(
"""ISO 4217"""
currencyCode: String!
Expand Down Expand Up @@ -1112,9 +1073,7 @@ type subscription_root {
where: lightning_address_bool_exp
): [lightning_address!]!

"""
fetch data from the table: "token"
"""
"""TEST COMMENT"""
token(
"""distinct select on columns"""
distinct_on: [token_select_column!]
Expand Down
Loading
Loading