Skip to content

Commit e61f30c

Browse files
committed
fixup! Fix RampBankFormScene UI & UX
Wrap KYC form onSubmit in try-catch to reject Promise on errors, preventing workflow hang when vault, KYC status, or webview fails.
1 parent 8c68d1e commit e61f30c

File tree

1 file changed

+108
-104
lines changed

1 file changed

+108
-104
lines changed

src/plugins/ramps/infinite/workflows/kycWorkflow.ts

Lines changed: 108 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -67,122 +67,126 @@ export const kycWorkflow = async (params: Params): Promise<void> => {
6767
navigationFlow.navigate('kycForm', {
6868
headerTitle: lstrings.ramp_plugin_kyc_title,
6969
onSubmit: async (contactInfo: KycFormData) => {
70-
// Create customer profile with flattened schema
71-
const customerResponse = await infiniteApi
72-
.createCustomer({
73-
type: 'individual',
74-
countryCode,
75-
contactInformation: {
76-
email: contactInfo.email
77-
},
78-
personalInfo: {
79-
firstName: contactInfo.firstName,
80-
lastName: contactInfo.lastName
81-
},
82-
address: {
83-
addressLine1: contactInfo.address1,
84-
addressLine2: contactInfo.address2,
85-
city: contactInfo.city,
86-
state: contactInfo.state,
87-
postalCode: contactInfo.postalCode,
88-
country: countryCode
89-
},
90-
companyInformation: undefined
91-
})
92-
.catch((error: unknown) => {
93-
return { error }
94-
})
95-
96-
if ('error' in customerResponse) {
97-
if (
98-
customerResponse.error instanceof InfiniteApiError &&
99-
customerResponse.error.detail.includes('duplicate_record')
100-
) {
101-
throw new I18nError(
102-
lstrings.ramp_signup_failed_title,
103-
lstrings.ramp_signup_failed_account_existsmessage
104-
)
70+
try {
71+
// Create customer profile with flattened schema
72+
const customerResponse = await infiniteApi
73+
.createCustomer({
74+
type: 'individual',
75+
countryCode,
76+
contactInformation: {
77+
email: contactInfo.email
78+
},
79+
personalInfo: {
80+
firstName: contactInfo.firstName,
81+
lastName: contactInfo.lastName
82+
},
83+
address: {
84+
addressLine1: contactInfo.address1,
85+
addressLine2: contactInfo.address2,
86+
city: contactInfo.city,
87+
state: contactInfo.state,
88+
postalCode: contactInfo.postalCode,
89+
country: countryCode
90+
},
91+
companyInformation: undefined
92+
})
93+
.catch((error: unknown) => {
94+
return { error }
95+
})
96+
97+
if ('error' in customerResponse) {
98+
if (
99+
customerResponse.error instanceof InfiniteApiError &&
100+
customerResponse.error.detail.includes('duplicate_record')
101+
) {
102+
throw new I18nError(
103+
lstrings.ramp_signup_failed_title,
104+
lstrings.ramp_signup_failed_account_existsmessage
105+
)
106+
}
107+
108+
throw customerResponse.error
105109
}
106110

107-
throw customerResponse.error
108-
}
111+
// Check if OTP was sent (existing email case)
112+
if ('otpSent' in customerResponse) {
113+
const otpResult = await showOtpModal(infiniteApi, contactInfo.email)
109114

110-
// Check if OTP was sent (existing email case)
111-
if ('otpSent' in customerResponse) {
112-
const otpResult = await showOtpModal(infiniteApi, contactInfo.email)
115+
if (otpResult == null) {
116+
// User cancelled OTP verification - resolve(false) to let the
117+
// workflow handle this gracefully at the top level rather than
118+
// showing an error in the form scene.
119+
resolve(false)
120+
return
121+
}
113122

114-
if (otpResult == null) {
115-
// User cancelled OTP verification - resolve(false) to let the
116-
// workflow handle this gracefully at the top level rather than
117-
// showing an error in the form scene.
118-
resolve(false)
119-
return
123+
// Store customer ID from OTP verification response
124+
infiniteApi.saveCustomerId(otpResult.customer.id)
125+
} else {
126+
// Store customer ID directly in state
127+
infiniteApi.saveCustomerId(customerResponse.customer.id)
120128
}
121129

122-
// Store customer ID from OTP verification response
123-
infiniteApi.saveCustomerId(otpResult.customer.id)
124-
} else {
125-
// Store customer ID directly in state
126-
infiniteApi.saveCustomerId(customerResponse.customer.id)
127-
}
130+
// Save or update personal info in vault
131+
const personalInfoUuid = await vault.getUuid('personalInfo', 0)
132+
const personalInfo = {
133+
type: 'personalInfo' as const,
134+
name: {
135+
firstName: contactInfo.firstName,
136+
lastName: contactInfo.lastName
137+
},
138+
email: contactInfo.email
139+
}
140+
if (personalInfoUuid != null) {
141+
await vault.updatePersonalInfo(personalInfoUuid, personalInfo)
142+
} else {
143+
await vault.createPersonalInfo(personalInfo)
144+
}
128145

129-
// Save or update personal info in vault
130-
const personalInfoUuid = await vault.getUuid('personalInfo', 0)
131-
const personalInfo = {
132-
type: 'personalInfo' as const,
133-
name: {
134-
firstName: contactInfo.firstName,
135-
lastName: contactInfo.lastName
136-
},
137-
email: contactInfo.email
138-
}
139-
if (personalInfoUuid != null) {
140-
await vault.updatePersonalInfo(personalInfoUuid, personalInfo)
141-
} else {
142-
await vault.createPersonalInfo(personalInfo)
143-
}
146+
// Save or update address info in vault
147+
const addressInfoUuid = await vault.getUuid('addressInfo', 0)
148+
const addressInfo = {
149+
type: 'addressInfo' as const,
150+
line1: contactInfo.address1,
151+
line2: contactInfo.address2,
152+
city: contactInfo.city,
153+
state: contactInfo.state,
154+
postalCode: contactInfo.postalCode,
155+
countryCode
156+
}
157+
if (addressInfoUuid != null) {
158+
await vault.updateAddressInfo(addressInfoUuid, addressInfo)
159+
} else {
160+
await vault.createAddressInfo(addressInfo)
161+
}
144162

145-
// Save or update address info in vault
146-
const addressInfoUuid = await vault.getUuid('addressInfo', 0)
147-
const addressInfo = {
148-
type: 'addressInfo' as const,
149-
line1: contactInfo.address1,
150-
line2: contactInfo.address2,
151-
city: contactInfo.city,
152-
state: contactInfo.state,
153-
postalCode: contactInfo.postalCode,
154-
countryCode
155-
}
156-
if (addressInfoUuid != null) {
157-
await vault.updateAddressInfo(addressInfoUuid, addressInfo)
158-
} else {
159-
await vault.createAddressInfo(addressInfo)
160-
}
163+
// Get customer ID from auth state (set either from direct response or OTP)
164+
const newCustomerId = infiniteApi.getAuthState().customerId
165+
if (newCustomerId == null) {
166+
throw new ExitError('Customer ID is missing after creation')
167+
}
161168

162-
// Get customer ID from auth state (set either from direct response or OTP)
163-
const newCustomerId = infiniteApi.getAuthState().customerId
164-
if (newCustomerId == null) {
165-
throw new ExitError('Customer ID is missing after creation')
166-
}
169+
// If KYC is already approved (possible when linking an existing email),
170+
// skip opening the KYC webview entirely.
171+
const newCustomerKycStatus = await infiniteApi.getKycStatus(
172+
newCustomerId
173+
)
174+
if (newCustomerKycStatus.kycStatus === 'ACTIVE') {
175+
resolve(true)
176+
return
177+
}
167178

168-
// If KYC is already approved (possible when linking an existing email),
169-
// skip opening the KYC webview entirely.
170-
const newCustomerKycStatus = await infiniteApi.getKycStatus(
171-
newCustomerId
172-
)
173-
if (newCustomerKycStatus.kycStatus === 'ACTIVE') {
179+
// Open KYC webview
180+
await openKycWebView(
181+
navigationFlow,
182+
infiniteApi,
183+
newCustomerId,
184+
pluginId
185+
)
174186
resolve(true)
175-
return
187+
} catch (error: unknown) {
188+
reject(error)
176189
}
177-
178-
// Open KYC webview
179-
await openKycWebView(
180-
navigationFlow,
181-
infiniteApi,
182-
newCustomerId,
183-
pluginId
184-
)
185-
resolve(true)
186190
},
187191
onCancel: () => {
188192
resolve(false)

0 commit comments

Comments
 (0)