@metamask/ramps-controller 20.2.0 → 21.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/dist/NeoBankService-method-action-types.d.ts +126 -0
  3. package/dist/NeoBankService-method-action-types.d.ts.map +1 -0
  4. package/dist/{TransakService-method-action-types.mjs → NeoBankService-method-action-types.js} +1 -1
  5. package/dist/NeoBankService-method-action-types.js.map +1 -0
  6. package/dist/NeoBankService.d.ts +191 -0
  7. package/dist/NeoBankService.d.ts.map +1 -0
  8. package/dist/NeoBankService.js +380 -0
  9. package/dist/NeoBankService.js.map +1 -0
  10. package/dist/{RampsController-method-action-types.d.mts → RampsController-method-action-types.d.ts} +93 -3
  11. package/dist/RampsController-method-action-types.d.ts.map +1 -0
  12. package/dist/{RampsController-method-action-types.mjs → RampsController-method-action-types.js} +1 -1
  13. package/dist/RampsController-method-action-types.js.map +1 -0
  14. package/dist/{RampsController.d.cts → RampsController.d.ts} +164 -17
  15. package/dist/RampsController.d.ts.map +1 -0
  16. package/dist/{RampsController.mjs → RampsController.js} +1064 -582
  17. package/dist/RampsController.js.map +1 -0
  18. package/dist/{RampsService-method-action-types.d.cts → RampsService-method-action-types.d.ts} +2 -2
  19. package/dist/RampsService-method-action-types.d.ts.map +1 -0
  20. package/dist/{RampsService-method-action-types.mjs → RampsService-method-action-types.js} +1 -1
  21. package/dist/RampsService-method-action-types.js.map +1 -0
  22. package/dist/{RampsService.d.mts → RampsService.d.ts} +5 -5
  23. package/dist/RampsService.d.ts.map +1 -0
  24. package/dist/{RampsService.mjs → RampsService.js} +159 -147
  25. package/dist/RampsService.js.map +1 -0
  26. package/dist/{RequestCache.d.cts → RequestCache.d.ts} +3 -3
  27. package/dist/RequestCache.d.ts.map +1 -0
  28. package/dist/{RequestCache.mjs → RequestCache.js} +1 -1
  29. package/dist/RequestCache.js.map +1 -0
  30. package/dist/{TransakService-method-action-types.d.cts → TransakService-method-action-types.d.ts} +2 -2
  31. package/dist/TransakService-method-action-types.d.ts.map +1 -0
  32. package/dist/TransakService-method-action-types.js +6 -0
  33. package/dist/TransakService-method-action-types.js.map +1 -0
  34. package/dist/{TransakService.d.mts → TransakService.d.ts} +6 -6
  35. package/dist/TransakService.d.ts.map +1 -0
  36. package/dist/TransakService.js +746 -0
  37. package/dist/TransakService.js.map +1 -0
  38. package/dist/autoramp-types.d.ts +22 -0
  39. package/dist/autoramp-types.d.ts.map +1 -0
  40. package/dist/autoramp-types.js +2 -0
  41. package/dist/autoramp-types.js.map +1 -0
  42. package/dist/autorampAccount.d.ts +126 -0
  43. package/dist/autorampAccount.d.ts.map +1 -0
  44. package/dist/autorampAccount.js +147 -0
  45. package/dist/autorampAccount.js.map +1 -0
  46. package/dist/{client-identity.d.cts → client-identity.d.ts} +1 -1
  47. package/dist/client-identity.d.ts.map +1 -0
  48. package/dist/{client-identity.mjs → client-identity.js} +1 -1
  49. package/dist/client-identity.js.map +1 -0
  50. package/dist/{errorNormalization.d.mts → errorNormalization.d.ts} +1 -1
  51. package/dist/errorNormalization.d.ts.map +1 -0
  52. package/dist/{errorNormalization.mjs → errorNormalization.js} +1 -1
  53. package/dist/errorNormalization.js.map +1 -0
  54. package/dist/{featureFlags.d.mts → featureFlags.d.ts} +2 -2
  55. package/dist/featureFlags.d.ts.map +1 -0
  56. package/dist/{featureFlags.mjs → featureFlags.js} +1 -1
  57. package/dist/featureFlags.js.map +1 -0
  58. package/dist/index.d.ts +35 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +18 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/{orderStatus.d.mts → orderStatus.d.ts} +2 -2
  63. package/dist/orderStatus.d.ts.map +1 -0
  64. package/dist/{orderStatus.mjs → orderStatus.js} +2 -2
  65. package/dist/orderStatus.js.map +1 -0
  66. package/dist/ownership-message.d.ts +22 -0
  67. package/dist/ownership-message.d.ts.map +1 -0
  68. package/dist/ownership-message.js +22 -0
  69. package/dist/ownership-message.js.map +1 -0
  70. package/dist/{paymentMethodMerge.d.cts → paymentMethodMerge.d.ts} +2 -2
  71. package/dist/paymentMethodMerge.d.ts.map +1 -0
  72. package/dist/{paymentMethodMerge.mjs → paymentMethodMerge.js} +1 -1
  73. package/dist/paymentMethodMerge.js.map +1 -0
  74. package/dist/{providerAvailability.d.mts → providerAvailability.d.ts} +2 -2
  75. package/dist/providerAvailability.d.ts.map +1 -0
  76. package/dist/{providerAvailability.mjs → providerAvailability.js} +1 -1
  77. package/dist/providerAvailability.js.map +1 -0
  78. package/dist/{quoteClassification.d.cts → quoteClassification.d.ts} +2 -2
  79. package/dist/quoteClassification.d.ts.map +1 -0
  80. package/dist/{quoteClassification.mjs → quoteClassification.js} +1 -1
  81. package/dist/quoteClassification.js.map +1 -0
  82. package/dist/{rampsErrorCodes.d.cts → rampsErrorCodes.d.ts} +2 -2
  83. package/dist/rampsErrorCodes.d.ts.map +1 -0
  84. package/dist/{rampsErrorCodes.mjs → rampsErrorCodes.js} +1 -1
  85. package/dist/rampsErrorCodes.js.map +1 -0
  86. package/dist/{selectors.d.mts → selectors.d.ts} +3 -3
  87. package/dist/selectors.d.ts.map +1 -0
  88. package/dist/{selectors.mjs → selectors.js} +2 -2
  89. package/dist/selectors.js.map +1 -0
  90. package/dist/{transakApiErrorUtils.d.cts → transakApiErrorUtils.d.ts} +1 -1
  91. package/dist/transakApiErrorUtils.d.ts.map +1 -0
  92. package/dist/{transakApiErrorUtils.mjs → transakApiErrorUtils.js} +3 -3
  93. package/dist/transakApiErrorUtils.js.map +1 -0
  94. package/dist/{transakErrorCodes.d.cts → transakErrorCodes.d.ts} +3 -3
  95. package/dist/transakErrorCodes.d.ts.map +1 -0
  96. package/dist/{transakErrorCodes.mjs → transakErrorCodes.js} +1 -1
  97. package/dist/transakErrorCodes.js.map +1 -0
  98. package/dist/wallet-registration-machine.d.ts +81 -0
  99. package/dist/wallet-registration-machine.d.ts.map +1 -0
  100. package/dist/wallet-registration-machine.js +139 -0
  101. package/dist/wallet-registration-machine.js.map +1 -0
  102. package/dist/wallet-registration-service.d.ts +144 -0
  103. package/dist/wallet-registration-service.d.ts.map +1 -0
  104. package/dist/wallet-registration-service.js +335 -0
  105. package/dist/wallet-registration-service.js.map +1 -0
  106. package/package.json +17 -21
  107. package/dist/RampsController-method-action-types.cjs +0 -7
  108. package/dist/RampsController-method-action-types.cjs.map +0 -1
  109. package/dist/RampsController-method-action-types.d.cts +0 -668
  110. package/dist/RampsController-method-action-types.d.cts.map +0 -1
  111. package/dist/RampsController-method-action-types.d.mts.map +0 -1
  112. package/dist/RampsController-method-action-types.mjs.map +0 -1
  113. package/dist/RampsController.cjs +0 -2429
  114. package/dist/RampsController.cjs.map +0 -1
  115. package/dist/RampsController.d.cts.map +0 -1
  116. package/dist/RampsController.d.mts +0 -821
  117. package/dist/RampsController.d.mts.map +0 -1
  118. package/dist/RampsController.mjs.map +0 -1
  119. package/dist/RampsService-method-action-types.cjs +0 -7
  120. package/dist/RampsService-method-action-types.cjs.map +0 -1
  121. package/dist/RampsService-method-action-types.d.cts.map +0 -1
  122. package/dist/RampsService-method-action-types.d.mts +0 -171
  123. package/dist/RampsService-method-action-types.d.mts.map +0 -1
  124. package/dist/RampsService-method-action-types.mjs.map +0 -1
  125. package/dist/RampsService.cjs +0 -708
  126. package/dist/RampsService.cjs.map +0 -1
  127. package/dist/RampsService.d.cts +0 -944
  128. package/dist/RampsService.d.cts.map +0 -1
  129. package/dist/RampsService.d.mts.map +0 -1
  130. package/dist/RampsService.mjs.map +0 -1
  131. package/dist/RequestCache.cjs +0 -103
  132. package/dist/RequestCache.cjs.map +0 -1
  133. package/dist/RequestCache.d.cts.map +0 -1
  134. package/dist/RequestCache.d.mts +0 -110
  135. package/dist/RequestCache.d.mts.map +0 -1
  136. package/dist/RequestCache.mjs.map +0 -1
  137. package/dist/TransakService-method-action-types.cjs +0 -7
  138. package/dist/TransakService-method-action-types.cjs.map +0 -1
  139. package/dist/TransakService-method-action-types.d.cts.map +0 -1
  140. package/dist/TransakService-method-action-types.d.mts +0 -140
  141. package/dist/TransakService-method-action-types.d.mts.map +0 -1
  142. package/dist/TransakService-method-action-types.mjs.map +0 -1
  143. package/dist/TransakService.cjs +0 -743
  144. package/dist/TransakService.cjs.map +0 -1
  145. package/dist/TransakService.d.cts +0 -370
  146. package/dist/TransakService.d.cts.map +0 -1
  147. package/dist/TransakService.d.mts.map +0 -1
  148. package/dist/TransakService.mjs +0 -734
  149. package/dist/TransakService.mjs.map +0 -1
  150. package/dist/client-identity.cjs +0 -28
  151. package/dist/client-identity.cjs.map +0 -1
  152. package/dist/client-identity.d.cts.map +0 -1
  153. package/dist/client-identity.d.mts +0 -24
  154. package/dist/client-identity.d.mts.map +0 -1
  155. package/dist/client-identity.mjs.map +0 -1
  156. package/dist/errorNormalization.cjs +0 -84
  157. package/dist/errorNormalization.cjs.map +0 -1
  158. package/dist/errorNormalization.d.cts +0 -56
  159. package/dist/errorNormalization.d.cts.map +0 -1
  160. package/dist/errorNormalization.d.mts.map +0 -1
  161. package/dist/errorNormalization.mjs.map +0 -1
  162. package/dist/featureFlags.cjs +0 -144
  163. package/dist/featureFlags.cjs.map +0 -1
  164. package/dist/featureFlags.d.cts +0 -82
  165. package/dist/featureFlags.d.cts.map +0 -1
  166. package/dist/featureFlags.d.mts.map +0 -1
  167. package/dist/featureFlags.mjs.map +0 -1
  168. package/dist/index.cjs +0 -63
  169. package/dist/index.cjs.map +0 -1
  170. package/dist/index.d.cts +0 -26
  171. package/dist/index.d.cts.map +0 -1
  172. package/dist/index.d.mts +0 -26
  173. package/dist/index.d.mts.map +0 -1
  174. package/dist/index.mjs +0 -14
  175. package/dist/index.mjs.map +0 -1
  176. package/dist/orderStatus.cjs +0 -34
  177. package/dist/orderStatus.cjs.map +0 -1
  178. package/dist/orderStatus.d.cts +0 -18
  179. package/dist/orderStatus.d.cts.map +0 -1
  180. package/dist/orderStatus.d.mts.map +0 -1
  181. package/dist/orderStatus.mjs.map +0 -1
  182. package/dist/paymentMethodMerge.cjs +0 -51
  183. package/dist/paymentMethodMerge.cjs.map +0 -1
  184. package/dist/paymentMethodMerge.d.cts.map +0 -1
  185. package/dist/paymentMethodMerge.d.mts +0 -26
  186. package/dist/paymentMethodMerge.d.mts.map +0 -1
  187. package/dist/paymentMethodMerge.mjs.map +0 -1
  188. package/dist/providerAvailability.cjs +0 -134
  189. package/dist/providerAvailability.cjs.map +0 -1
  190. package/dist/providerAvailability.d.cts +0 -101
  191. package/dist/providerAvailability.d.cts.map +0 -1
  192. package/dist/providerAvailability.d.mts.map +0 -1
  193. package/dist/providerAvailability.mjs.map +0 -1
  194. package/dist/quoteClassification.cjs +0 -44
  195. package/dist/quoteClassification.cjs.map +0 -1
  196. package/dist/quoteClassification.d.cts.map +0 -1
  197. package/dist/quoteClassification.d.mts +0 -33
  198. package/dist/quoteClassification.d.mts.map +0 -1
  199. package/dist/quoteClassification.mjs.map +0 -1
  200. package/dist/rampsErrorCodes.cjs +0 -11
  201. package/dist/rampsErrorCodes.cjs.map +0 -1
  202. package/dist/rampsErrorCodes.d.cts.map +0 -1
  203. package/dist/rampsErrorCodes.d.mts +0 -9
  204. package/dist/rampsErrorCodes.d.mts.map +0 -1
  205. package/dist/rampsErrorCodes.mjs.map +0 -1
  206. package/dist/selectors.cjs +0 -85
  207. package/dist/selectors.cjs.map +0 -1
  208. package/dist/selectors.d.cts +0 -78
  209. package/dist/selectors.d.cts.map +0 -1
  210. package/dist/selectors.d.mts.map +0 -1
  211. package/dist/selectors.mjs.map +0 -1
  212. package/dist/transakApiErrorUtils.cjs +0 -15
  213. package/dist/transakApiErrorUtils.cjs.map +0 -1
  214. package/dist/transakApiErrorUtils.d.cts.map +0 -1
  215. package/dist/transakApiErrorUtils.d.mts +0 -3
  216. package/dist/transakApiErrorUtils.d.mts.map +0 -1
  217. package/dist/transakApiErrorUtils.mjs.map +0 -1
  218. package/dist/transakErrorCodes.cjs +0 -14
  219. package/dist/transakErrorCodes.cjs.map +0 -1
  220. package/dist/transakErrorCodes.d.cts.map +0 -1
  221. package/dist/transakErrorCodes.d.mts +0 -12
  222. package/dist/transakErrorCodes.d.mts.map +0 -1
  223. package/dist/transakErrorCodes.mjs.map +0 -1
@@ -0,0 +1,746 @@
1
+ import { createServicePolicy, HttpError } from '@metamask/controller-utils';
2
+ import packageJson from '../package.json';
3
+ import { addRampsClientIdentityParams } from './client-identity.js';
4
+ import { RAMPS_SDK_VERSION } from './RampsService.js';
5
+ import { TRANSAK_ERROR_CODES } from './transakErrorCodes.js';
6
+ // === ENVIRONMENT ===
7
+ export var TransakEnvironment;
8
+ (function (TransakEnvironment) {
9
+ TransakEnvironment["Production"] = "production";
10
+ TransakEnvironment["Staging"] = "staging";
11
+ TransakEnvironment["Development"] = "development";
12
+ })(TransakEnvironment || (TransakEnvironment = {}));
13
+ var TransakApiProviders;
14
+ (function (TransakApiProviders) {
15
+ TransakApiProviders["TransakNative"] = "transak-native";
16
+ TransakApiProviders["TransakNativeStaging"] = "transak-native-staging";
17
+ })(TransakApiProviders || (TransakApiProviders = {}));
18
+ // === ORDER ID UTILITIES ===
19
+ export class TransakOrderIdTransformer {
20
+ static depositOrderIdToTransakOrderId(depositOrderId) {
21
+ const parts = depositOrderId.split('/');
22
+ return parts[parts.length - 1];
23
+ }
24
+ static transakOrderIdToDepositOrderId(transakOrderId, environment) {
25
+ const provider = environment === TransakEnvironment.Production
26
+ ? 'transak-native'
27
+ : 'transak-native-staging';
28
+ return `/providers/${provider}/orders/${transakOrderId}`;
29
+ }
30
+ static isDepositOrderId(orderId) {
31
+ return orderId.startsWith('/providers/');
32
+ }
33
+ static extractTransakOrderId(orderId) {
34
+ return this.isDepositOrderId(orderId)
35
+ ? this.depositOrderIdToTransakOrderId(orderId)
36
+ : orderId;
37
+ }
38
+ }
39
+ // === MESSENGER ===
40
+ const serviceName = 'TransakService';
41
+ const MESSENGER_EXPOSED_METHODS = [
42
+ 'setApiKey',
43
+ 'setAccessToken',
44
+ 'clearAccessToken',
45
+ 'sendUserOtp',
46
+ 'verifyUserOtp',
47
+ 'logout',
48
+ 'getUserDetails',
49
+ 'getBuyQuote',
50
+ 'getKycRequirement',
51
+ 'getAdditionalRequirements',
52
+ 'createOrder',
53
+ 'getOrder',
54
+ 'getUserLimits',
55
+ 'requestOtt',
56
+ 'generatePaymentWidgetUrl',
57
+ 'createWidgetUrl',
58
+ 'submitPurposeOfUsageForm',
59
+ 'patchUser',
60
+ 'submitSsnDetails',
61
+ 'confirmPayment',
62
+ 'getTranslation',
63
+ 'getIdProofStatus',
64
+ 'cancelOrder',
65
+ 'cancelAllActiveOrders',
66
+ 'getActiveOrders',
67
+ ];
68
+ // === HELPER FUNCTIONS ===
69
+ /**
70
+ * Maps ramps API payment method IDs (e.g., "/payments/debit-credit-card")
71
+ * to the deposit-format IDs expected by the translation endpoint
72
+ * (e.g., "credit_debit_card").
73
+ *
74
+ * The translation endpoint only understands the deposit-format IDs.
75
+ * Canonical IDs may arrive either with the "/payments/" prefix
76
+ * (e.g., "/payments/apple-pay") or without it (e.g., "apple-pay"), so both
77
+ * forms are accepted. If no mapping exists, the input is returned as-is (it
78
+ * may already be in the deposit format).
79
+ */
80
+ const RAMPS_TO_DEPOSIT_PAYMENT_METHOD = {
81
+ '/payments/debit-credit-card': 'credit_debit_card',
82
+ '/payments/apple-pay': 'apple_pay',
83
+ '/payments/google-pay': 'google_pay',
84
+ '/payments/sepa-bank-transfer': 'sepa_bank_transfer',
85
+ '/payments/wire-transfer': 'wire_transfer',
86
+ '/payments/gbp-bank-transfer': 'gbp_bank_transfer',
87
+ };
88
+ const PAYMENTS_PREFIX = '/payments/';
89
+ function normalizePaymentMethodForTranslation(paymentMethod) {
90
+ if (!paymentMethod) {
91
+ return undefined;
92
+ }
93
+ const prefixed = paymentMethod.startsWith(PAYMENTS_PREFIX)
94
+ ? paymentMethod
95
+ : `${PAYMENTS_PREFIX}${paymentMethod}`;
96
+ return (RAMPS_TO_DEPOSIT_PAYMENT_METHOD[paymentMethod] ??
97
+ RAMPS_TO_DEPOSIT_PAYMENT_METHOD[prefixed] ??
98
+ paymentMethod);
99
+ }
100
+ function getTransakApiBaseUrl(environment) {
101
+ switch (environment) {
102
+ case TransakEnvironment.Production:
103
+ return 'https://api-gateway.transak.com';
104
+ // Transak has no dev environment; development uses their staging gateway.
105
+ case TransakEnvironment.Staging:
106
+ case TransakEnvironment.Development:
107
+ return 'https://api-gateway-stg.transak.com';
108
+ default:
109
+ throw new Error(`Invalid Transak environment: ${String(environment)}`);
110
+ }
111
+ }
112
+ function getRampsBaseUrl(environment) {
113
+ switch (environment) {
114
+ case TransakEnvironment.Production:
115
+ return 'https://on-ramp.api.cx.metamask.io';
116
+ case TransakEnvironment.Staging:
117
+ return 'https://on-ramp.uat-api.cx.metamask.io';
118
+ case TransakEnvironment.Development:
119
+ return 'https://on-ramp.dev-api.cx.metamask.io';
120
+ default:
121
+ throw new Error(`Invalid Transak environment: ${String(environment)}`);
122
+ }
123
+ }
124
+ function getRampsProviderPath(environment) {
125
+ // The dev ramps API registers the same `transak-native-staging` provider
126
+ // id as UAT; only production uses `transak-native`.
127
+ const providerId = environment === TransakEnvironment.Production
128
+ ? TransakApiProviders.TransakNative
129
+ : TransakApiProviders.TransakNativeStaging;
130
+ return `/providers/${providerId}`;
131
+ }
132
+ function getPaymentWidgetBaseUrl(environment) {
133
+ switch (environment) {
134
+ case TransakEnvironment.Production:
135
+ return 'https://global.transak.com';
136
+ // Transak has no dev environment; development uses their staging widget.
137
+ case TransakEnvironment.Staging:
138
+ case TransakEnvironment.Development:
139
+ return 'https://global-stg.transak.com';
140
+ default:
141
+ throw new Error(`Invalid Transak environment: ${String(environment)}`);
142
+ }
143
+ }
144
+ /**
145
+ * Transak requires `referrerDomain` in `widgetParams` alongside the partner
146
+ * API key (which the ramps API proxy injects server-side). Identifies the
147
+ * MetaMask client to Transak. Default when the client does not pass a
148
+ * `referrerDomain` constructor option (e.g. the mobile app passes its
149
+ * package name / bundle id).
150
+ */
151
+ const TRANSAK_REFERRER_DOMAIN = 'metamask.io';
152
+ // === TRANSAK API ERROR ===
153
+ export class TransakApiError extends HttpError {
154
+ errorCode;
155
+ apiMessage;
156
+ constructor(status, message, errorCode, apiMessage) {
157
+ super(status, message);
158
+ this.errorCode = errorCode;
159
+ this.apiMessage = apiMessage;
160
+ }
161
+ }
162
+ // === SERVICE DEFINITION ===
163
+ export class TransakService {
164
+ name;
165
+ #messenger;
166
+ #fetch;
167
+ #policy;
168
+ #noRetryPolicy;
169
+ #environment;
170
+ #context;
171
+ #orderRetryDelayMs;
172
+ #apiKey = null;
173
+ #accessToken = null;
174
+ /**
175
+ * Optional ramps API base URL override for local development (mirrors
176
+ * `RampsService`'s `baseUrlOverride`). Applies to the requests this service
177
+ * sends to the ramps API (orders, widget-url proxy), not to direct Transak
178
+ * API calls.
179
+ */
180
+ #rampsApiBaseUrlOverride;
181
+ /**
182
+ * Identifies the client to Transak in `widgetParams` (e.g. the mobile app's
183
+ * package name / bundle id). Defaults to `metamask.io`.
184
+ */
185
+ #referrerDomain;
186
+ #clientIdentity;
187
+ constructor({ messenger, environment = TransakEnvironment.Staging, context, fetch: fetchFunction, apiKey, policyOptions = {}, orderRetryDelayMs = 2000, rampsApiBaseUrlOverride, referrerDomain = TRANSAK_REFERRER_DOMAIN, clientProduct, clientVersion, }) {
188
+ this.name = serviceName;
189
+ this.#messenger = messenger;
190
+ this.#fetch = fetchFunction;
191
+ this.#policy = createServicePolicy(policyOptions);
192
+ this.#noRetryPolicy = createServicePolicy({
193
+ ...policyOptions,
194
+ maxRetries: 0,
195
+ });
196
+ this.#environment = environment;
197
+ this.#context = context;
198
+ this.#apiKey = apiKey ?? null;
199
+ this.#orderRetryDelayMs = orderRetryDelayMs;
200
+ this.#rampsApiBaseUrlOverride = rampsApiBaseUrlOverride;
201
+ this.#referrerDomain = referrerDomain;
202
+ this.#clientIdentity = {
203
+ clientProduct,
204
+ clientVersion,
205
+ };
206
+ this.#messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
207
+ }
208
+ setApiKey(apiKey) {
209
+ this.#apiKey = apiKey;
210
+ }
211
+ getApiKey() {
212
+ return this.#apiKey;
213
+ }
214
+ #ensureApiKey() {
215
+ if (!this.#apiKey) {
216
+ throw new Error('Transak API key is required but not set.');
217
+ }
218
+ return this.#apiKey;
219
+ }
220
+ setAccessToken(token) {
221
+ this.#accessToken = token;
222
+ }
223
+ getAccessToken() {
224
+ return this.#accessToken;
225
+ }
226
+ clearAccessToken() {
227
+ this.#accessToken = null;
228
+ }
229
+ #ensureAccessToken() {
230
+ if (!this.#accessToken?.accessToken) {
231
+ throw new HttpError(401, 'Authentication required. Please log in to continue.');
232
+ }
233
+ const createdTime = new Date(this.#accessToken.created).getTime();
234
+ const tokenAgeMs = Date.now() - createdTime;
235
+ if (tokenAgeMs > this.#accessToken.ttl * 1000) {
236
+ this.clearAccessToken();
237
+ throw new HttpError(401, 'Authentication token has expired. Please log in again.');
238
+ }
239
+ }
240
+ #getHeaders() {
241
+ const headers = {
242
+ 'Content-Type': 'application/json',
243
+ Accept: 'application/json',
244
+ };
245
+ if (this.#accessToken?.accessToken) {
246
+ headers.authorization = this.#accessToken.accessToken;
247
+ }
248
+ return headers;
249
+ }
250
+ async #throwTransakApiError(fetchResponse, url) {
251
+ let errorBody = '';
252
+ let errorCode;
253
+ let apiMessage;
254
+ try {
255
+ errorBody = await fetchResponse.text();
256
+ const parsed = JSON.parse(errorBody);
257
+ errorCode =
258
+ parsed?.error?.code ??
259
+ (parsed?.error?.errorCode !== null &&
260
+ parsed?.error?.errorCode !== undefined
261
+ ? String(parsed.error.errorCode)
262
+ : undefined);
263
+ apiMessage =
264
+ typeof parsed?.error?.message === 'string'
265
+ ? parsed.error.message
266
+ : undefined;
267
+ }
268
+ catch {
269
+ // ignore body read/parse failures
270
+ }
271
+ throw new TransakApiError(fetchResponse.status, `Fetching '${url.toString()}' failed with status '${fetchResponse.status}'${errorBody ? `: ${errorBody}` : ''}`, errorCode, apiMessage);
272
+ }
273
+ async #transakGet(path, params) {
274
+ const baseUrl = getTransakApiBaseUrl(this.#environment);
275
+ const url = new URL(path, baseUrl);
276
+ if (params) {
277
+ for (const [key, value] of Object.entries(params)) {
278
+ if (value !== null && value !== undefined) {
279
+ url.searchParams.set(key, value);
280
+ }
281
+ }
282
+ }
283
+ const apiKey = this.#ensureApiKey();
284
+ url.searchParams.set('apiKey', apiKey);
285
+ const response = await this.#policy.execute(async () => {
286
+ const fetchResponse = await this.#fetch(url.toString(), {
287
+ method: 'GET',
288
+ headers: this.#getHeaders(),
289
+ });
290
+ if (!fetchResponse.ok) {
291
+ await this.#throwTransakApiError(fetchResponse, url);
292
+ }
293
+ return fetchResponse.json();
294
+ });
295
+ return response.data;
296
+ }
297
+ async #transakPost(path, body, options = {}) {
298
+ const apiKey = this.#ensureApiKey();
299
+ const baseUrl = getTransakApiBaseUrl(this.#environment);
300
+ const url = new URL(path, baseUrl);
301
+ const requestBody = {
302
+ ...(body ?? {}),
303
+ apiKey,
304
+ };
305
+ const policy = options.policy ?? this.#policy;
306
+ const response = await policy.execute(async () => {
307
+ const fetchResponse = await this.#fetch(url.toString(), {
308
+ method: 'POST',
309
+ headers: this.#getHeaders(),
310
+ body: JSON.stringify(requestBody),
311
+ });
312
+ if (!fetchResponse.ok) {
313
+ await this.#throwTransakApiError(fetchResponse, url);
314
+ }
315
+ return fetchResponse.json();
316
+ });
317
+ return response.data;
318
+ }
319
+ async #transakPatch(path, body) {
320
+ const apiKey = this.#ensureApiKey();
321
+ const baseUrl = getTransakApiBaseUrl(this.#environment);
322
+ const url = new URL(path, baseUrl);
323
+ url.searchParams.set('apiKey', apiKey);
324
+ const response = await this.#policy.execute(async () => {
325
+ const fetchResponse = await this.#fetch(url.toString(), {
326
+ method: 'PATCH',
327
+ headers: this.#getHeaders(),
328
+ body: JSON.stringify(body),
329
+ });
330
+ if (!fetchResponse.ok) {
331
+ await this.#throwTransakApiError(fetchResponse, url);
332
+ }
333
+ return fetchResponse.json();
334
+ });
335
+ return response.data;
336
+ }
337
+ async #transakDelete(path, params) {
338
+ const apiKey = this.#ensureApiKey();
339
+ const baseUrl = getTransakApiBaseUrl(this.#environment);
340
+ const url = new URL(path, baseUrl);
341
+ url.searchParams.set('apiKey', apiKey);
342
+ if (params) {
343
+ for (const [key, value] of Object.entries(params)) {
344
+ if (value !== null && value !== undefined) {
345
+ url.searchParams.set(key, value);
346
+ }
347
+ }
348
+ }
349
+ await this.#policy.execute(async () => {
350
+ const fetchResponse = await this.#fetch(url.toString(), {
351
+ method: 'DELETE',
352
+ headers: this.#getHeaders(),
353
+ });
354
+ if (!fetchResponse.ok) {
355
+ await this.#throwTransakApiError(fetchResponse, url);
356
+ }
357
+ });
358
+ }
359
+ /**
360
+ * Gets the ramps API base URL, respecting the local-development override
361
+ * when set (same semantics as `RampsService`'s `baseUrlOverride`).
362
+ *
363
+ * @returns The ramps API base URL to use.
364
+ */
365
+ #getRampsApiBaseUrl() {
366
+ return this.#rampsApiBaseUrlOverride ?? getRampsBaseUrl(this.#environment);
367
+ }
368
+ /**
369
+ * Adds the common request parameters to a ramps API proxy URL, mirroring
370
+ * `RampsService`'s `#addCommonParams`.
371
+ *
372
+ * @param url - The URL to add parameters to.
373
+ */
374
+ #addRampsCommonParams(url) {
375
+ url.searchParams.set('action', 'deposit');
376
+ url.searchParams.set('sdk', RAMPS_SDK_VERSION);
377
+ url.searchParams.set('controller', packageJson.version);
378
+ url.searchParams.set('context', this.#context);
379
+ // In the query string (not headers) so CDN-cached responses vary per
380
+ // client product / version.
381
+ addRampsClientIdentityParams(url, this.#clientIdentity);
382
+ }
383
+ async #ordersApiGet(path, params) {
384
+ const baseUrl = this.#getRampsApiBaseUrl();
385
+ const providerPath = getRampsProviderPath(this.#environment);
386
+ const url = new URL(`${providerPath}${path}`, baseUrl);
387
+ url.searchParams.set('action', 'deposit');
388
+ url.searchParams.set('context', this.#context);
389
+ // In the query string (not headers) so CDN-cached responses vary per
390
+ // client product / version.
391
+ addRampsClientIdentityParams(url, this.#clientIdentity);
392
+ if (params) {
393
+ for (const [key, value] of Object.entries(params)) {
394
+ if (value !== null && value !== undefined) {
395
+ url.searchParams.set(key, value);
396
+ }
397
+ }
398
+ }
399
+ const response = await this.#policy.execute(async () => {
400
+ const fetchResponse = await this.#fetch(url.toString(), {
401
+ method: 'GET',
402
+ headers: { Accept: 'application/json' },
403
+ });
404
+ if (!fetchResponse.ok) {
405
+ throw new HttpError(fetchResponse.status, `Fetching '${url.toString()}' failed with status '${fetchResponse.status}'`);
406
+ }
407
+ return fetchResponse.json();
408
+ });
409
+ return response;
410
+ }
411
+ // === PUBLIC API METHODS ===
412
+ async sendUserOtp(email) {
413
+ const result = await this.#transakPost('/api/v2/auth/login', { email });
414
+ return result;
415
+ }
416
+ async verifyUserOtp(email, verificationCode, stateToken) {
417
+ const responseData = await this.#transakPost('/api/v2/auth/verify', {
418
+ email,
419
+ otp: verificationCode,
420
+ stateToken,
421
+ }, { policy: this.#noRetryPolicy });
422
+ const accessToken = {
423
+ accessToken: responseData.accessToken,
424
+ ttl: responseData.ttl,
425
+ created: new Date(responseData.created),
426
+ };
427
+ this.setAccessToken(accessToken);
428
+ return accessToken;
429
+ }
430
+ async logout() {
431
+ this.#ensureAccessToken();
432
+ try {
433
+ const result = await this.#transakPost('/api/v1/auth/logout');
434
+ this.clearAccessToken();
435
+ return result;
436
+ }
437
+ catch (error) {
438
+ if (error instanceof HttpError && error.httpStatus === 401) {
439
+ this.clearAccessToken();
440
+ return 'user was already logged out';
441
+ }
442
+ throw error;
443
+ }
444
+ }
445
+ async getUserDetails() {
446
+ this.#ensureAccessToken();
447
+ return this.#transakGet('/api/v2/user/');
448
+ }
449
+ async getBuyQuote(genericFiatCurrency, genericCryptoCurrency, genericNetwork, genericPaymentMethod, fiatAmount) {
450
+ const normalizedPaymentMethod = normalizePaymentMethodForTranslation(genericPaymentMethod || undefined);
451
+ const translationRequest = {
452
+ cryptoCurrencyId: genericCryptoCurrency,
453
+ chainId: genericNetwork,
454
+ fiatCurrencyId: genericFiatCurrency,
455
+ paymentMethod: normalizedPaymentMethod,
456
+ };
457
+ const translation = await this.getTranslation(translationRequest);
458
+ const params = {
459
+ fiatCurrency: translation.fiatCurrency,
460
+ cryptoCurrency: translation.cryptoCurrency,
461
+ isBuyOrSell: 'BUY',
462
+ network: translation.network,
463
+ fiatAmount,
464
+ isFeeExcludedFromFiat: 'true',
465
+ };
466
+ if (translation.paymentMethod) {
467
+ params.paymentMethod = translation.paymentMethod;
468
+ }
469
+ return this.#transakGet('/api/v2/lookup/quotes', params);
470
+ }
471
+ async getKycRequirement(quoteId) {
472
+ this.#ensureAccessToken();
473
+ const result = await this.#transakGet('/api/v2/kyc/requirement', {
474
+ 'metadata[quoteId]': quoteId,
475
+ });
476
+ return result;
477
+ }
478
+ async getAdditionalRequirements(quoteId) {
479
+ this.#ensureAccessToken();
480
+ return this.#transakGet('/api/v2/kyc/additional-requirements', { 'metadata[quoteId]': quoteId });
481
+ }
482
+ async createOrder(quoteId, walletAddress, paymentMethodId) {
483
+ this.#ensureAccessToken();
484
+ const normalizedPaymentMethod = normalizePaymentMethodForTranslation(paymentMethodId);
485
+ const translation = await this.getTranslation({
486
+ paymentMethod: normalizedPaymentMethod,
487
+ });
488
+ const paymentInstrumentId = translation.paymentMethod ?? normalizedPaymentMethod;
489
+ try {
490
+ const transakOrder = await this.#transakPost('/api/v2/orders', {
491
+ quoteId,
492
+ walletAddress,
493
+ paymentInstrumentId,
494
+ });
495
+ const depositOrderId = TransakOrderIdTransformer.transakOrderIdToDepositOrderId(transakOrder.orderId, this.#environment);
496
+ return this.getOrder(depositOrderId, transakOrder.walletAddress, transakOrder.paymentDetails);
497
+ }
498
+ catch (error) {
499
+ if (error instanceof TransakApiError &&
500
+ error.httpStatus === 409 &&
501
+ error.errorCode === TRANSAK_ERROR_CODES.ORDER_EXISTS) {
502
+ await this.cancelAllActiveOrders();
503
+ await new Promise((resolve) => setTimeout(resolve, this.#orderRetryDelayMs));
504
+ const retryOrder = await this.#transakPost('/api/v2/orders', {
505
+ quoteId,
506
+ walletAddress,
507
+ paymentInstrumentId,
508
+ });
509
+ const retryDepositOrderId = TransakOrderIdTransformer.transakOrderIdToDepositOrderId(retryOrder.orderId, this.#environment);
510
+ return this.getOrder(retryDepositOrderId, retryOrder.walletAddress, retryOrder.paymentDetails);
511
+ }
512
+ throw error;
513
+ }
514
+ }
515
+ async getOrder(orderId, wallet, paymentDetails) {
516
+ let depositOrderId;
517
+ if (TransakOrderIdTransformer.isDepositOrderId(orderId)) {
518
+ depositOrderId = orderId;
519
+ }
520
+ else {
521
+ depositOrderId = TransakOrderIdTransformer.transakOrderIdToDepositOrderId(orderId, this.#environment);
522
+ }
523
+ const transakOrderId = TransakOrderIdTransformer.extractTransakOrderId(depositOrderId);
524
+ const order = await this.#ordersApiGet(`/orders/${transakOrderId}`, { wallet });
525
+ const orderWithId = {
526
+ ...order,
527
+ id: depositOrderId,
528
+ orderType: 'DEPOSIT',
529
+ };
530
+ if (paymentDetails && paymentDetails.length > 0) {
531
+ return { ...orderWithId, paymentDetails };
532
+ }
533
+ if (this.#accessToken?.accessToken) {
534
+ try {
535
+ const transakOrder = await this.#transakGet(`/api/v2/orders/${transakOrderId}`);
536
+ return { ...orderWithId, paymentDetails: transakOrder.paymentDetails };
537
+ }
538
+ catch {
539
+ return orderWithId;
540
+ }
541
+ }
542
+ return orderWithId;
543
+ }
544
+ async getUserLimits(fiatCurrency, paymentMethod, kycType) {
545
+ this.#ensureAccessToken();
546
+ const translation = await this.getTranslation({
547
+ paymentMethod: normalizePaymentMethodForTranslation(paymentMethod),
548
+ });
549
+ const params = {
550
+ isBuyOrSell: 'BUY',
551
+ kycType,
552
+ fiatCurrency,
553
+ };
554
+ if (translation.paymentMethod) {
555
+ params.paymentCategory = translation.paymentMethod;
556
+ }
557
+ return this.#transakGet('/api/v2/orders/user-limit', params);
558
+ }
559
+ /**
560
+ * @deprecated Use {@link createWidgetUrl} instead. The OTT flow requires the
561
+ * partner API key on the client and Transak is deprecating `request-ott`.
562
+ * @returns The one-time token response.
563
+ */
564
+ async requestOtt() {
565
+ this.#ensureAccessToken();
566
+ const result = await this.#transakPost('/api/v2/auth/request-ott');
567
+ return result;
568
+ }
569
+ /**
570
+ * @deprecated Use {@link createWidgetUrl} instead. This builds the widget
571
+ * URL client-side and embeds the partner API key in it.
572
+ * @param ottToken - The one-time token for widget authentication.
573
+ * @param quote - The buy quote to pre-fill in the widget.
574
+ * @param walletAddress - The destination wallet address.
575
+ * @param extraParams - Optional additional URL parameters.
576
+ * @returns The fully constructed widget URL string.
577
+ */
578
+ generatePaymentWidgetUrl(ottToken, quote, walletAddress, extraParams) {
579
+ const apiKey = this.#ensureApiKey();
580
+ const widgetBaseUrl = getPaymentWidgetBaseUrl(this.#environment);
581
+ const defaultParams = {
582
+ apiKey,
583
+ ott: ottToken,
584
+ fiatCurrency: quote.fiatCurrency,
585
+ cryptoCurrencyCode: quote.cryptoCurrency,
586
+ productsAvailed: 'BUY',
587
+ fiatAmount: quote.fiatAmount.toString(),
588
+ network: quote.network,
589
+ hideExchangeScreen: 'true',
590
+ walletAddress,
591
+ disableWalletAddressForm: 'true',
592
+ paymentMethod: quote.paymentMethod,
593
+ redirectURL: 'https://on-ramp-content.api.cx.metamask.io/regions/fake-callback',
594
+ hideMenu: 'true',
595
+ };
596
+ const params = new URLSearchParams({
597
+ ...defaultParams,
598
+ ...extraParams,
599
+ });
600
+ const widgetUrl = new URL(widgetBaseUrl);
601
+ widgetUrl.search = params.toString();
602
+ return widgetUrl.toString();
603
+ }
604
+ /**
605
+ * Creates a Transak payment widget URL through the ramps API proxy
606
+ * (`POST {rampsBaseUrl}/providers/{providerId}/widget-url`). The proxy
607
+ * injects the partner API key and derives the user IP server-side, so
608
+ * neither leaves the backend. Replaces the OTT flow ({@link requestOtt} +
609
+ * {@link generatePaymentWidgetUrl}).
610
+ *
611
+ * Requires both a Transak access token (user must be logged in to Transak)
612
+ * and a MetaMask bearer token from `AuthenticationController`.
613
+ *
614
+ * @param quote - The buy quote to pre-fill in the widget.
615
+ * @param walletAddress - The destination wallet address.
616
+ * @param extraParams - Optional additional widget parameters (e.g. theming).
617
+ * Keys must be on the proxy's allowlist or the request is rejected.
618
+ * @returns The single-use widget URL (expires after 5 minutes).
619
+ */
620
+ async createWidgetUrl(quote, walletAddress, extraParams) {
621
+ this.#ensureAccessToken();
622
+ const bearerToken = await this.#messenger.call('AuthenticationController:getBearerToken');
623
+ const baseUrl = this.#getRampsApiBaseUrl();
624
+ const providerPath = getRampsProviderPath(this.#environment);
625
+ const url = new URL(`${providerPath}/widget-url`, baseUrl);
626
+ this.#addRampsCommonParams(url);
627
+ const widgetParams = {
628
+ referrerDomain: this.#referrerDomain,
629
+ fiatCurrency: quote.fiatCurrency,
630
+ cryptoCurrencyCode: quote.cryptoCurrency,
631
+ fiatAmount: quote.fiatAmount,
632
+ network: quote.network,
633
+ paymentMethod: quote.paymentMethod,
634
+ walletAddress,
635
+ hideExchangeScreen: 'true',
636
+ disableWalletAddressEdit: 'true',
637
+ hideMenu: 'true',
638
+ redirectURL: 'https://on-ramp-content.api.cx.metamask.io/regions/fake-callback',
639
+ ...extraParams,
640
+ };
641
+ const headers = {
642
+ 'Content-Type': 'application/json',
643
+ Accept: 'application/json',
644
+ Authorization: `Bearer ${bearerToken}`,
645
+ };
646
+ if (this.#accessToken?.accessToken) {
647
+ headers['x-transak-access-token'] = this.#accessToken.accessToken;
648
+ }
649
+ const response = await this.#policy.execute(async () => {
650
+ const fetchResponse = await this.#fetch(url.toString(), {
651
+ method: 'POST',
652
+ headers,
653
+ body: JSON.stringify({ widgetParams }),
654
+ });
655
+ if (!fetchResponse.ok) {
656
+ await this.#throwTransakApiError(fetchResponse, url);
657
+ }
658
+ return fetchResponse.json();
659
+ });
660
+ return response.widgetUrl;
661
+ }
662
+ async submitPurposeOfUsageForm(purpose) {
663
+ this.#ensureAccessToken();
664
+ await this.#transakPost('/api/v2/kyc/purpose-of-usage', {
665
+ purposeList: purpose,
666
+ });
667
+ }
668
+ async patchUser(data) {
669
+ this.#ensureAccessToken();
670
+ return this.#transakPatch('/api/v2/kyc/user', data);
671
+ }
672
+ async submitSsnDetails(ssn, quoteId) {
673
+ this.#ensureAccessToken();
674
+ return this.#transakPost('/api/v2/kyc/ssn', { ssn, quoteId });
675
+ }
676
+ async confirmPayment(orderId, paymentMethodId) {
677
+ this.#ensureAccessToken();
678
+ const normalizedPaymentMethod = normalizePaymentMethodForTranslation(paymentMethodId);
679
+ const translation = await this.getTranslation({
680
+ paymentMethod: normalizedPaymentMethod,
681
+ });
682
+ const transakOrderId = TransakOrderIdTransformer.extractTransakOrderId(orderId);
683
+ return this.#transakPost('/api/v2/orders/payment-confirmation', {
684
+ orderId: transakOrderId,
685
+ paymentMethod: translation.paymentMethod ?? normalizedPaymentMethod,
686
+ });
687
+ }
688
+ async getTranslation(translationRequest) {
689
+ const baseUrl = getRampsBaseUrl(this.#environment);
690
+ const providerPath = getRampsProviderPath(this.#environment);
691
+ const url = new URL(`${providerPath}/native/translate`, baseUrl);
692
+ url.searchParams.set('action', 'deposit');
693
+ url.searchParams.set('context', this.#context);
694
+ const normalizedRequest = {
695
+ ...translationRequest,
696
+ paymentMethod: normalizePaymentMethodForTranslation(translationRequest.paymentMethod),
697
+ };
698
+ for (const [key, value] of Object.entries(normalizedRequest)) {
699
+ if (value !== undefined) {
700
+ url.searchParams.set(key, value);
701
+ }
702
+ }
703
+ const response = await this.#policy.execute(async () => {
704
+ const fetchResponse = await this.#fetch(url.toString(), {
705
+ method: 'GET',
706
+ headers: { Accept: 'application/json' },
707
+ });
708
+ if (!fetchResponse.ok) {
709
+ throw new HttpError(fetchResponse.status, `Fetching '${url.toString()}' failed with status '${fetchResponse.status}'`);
710
+ }
711
+ return fetchResponse.json();
712
+ });
713
+ return response;
714
+ }
715
+ async getIdProofStatus(workFlowRunId) {
716
+ this.#ensureAccessToken();
717
+ return this.#transakGet('/api/v2/kyc/id-proof-status', { workFlowRunId });
718
+ }
719
+ async cancelOrder(depositOrderId) {
720
+ this.#ensureAccessToken();
721
+ const transakOrderId = TransakOrderIdTransformer.extractTransakOrderId(depositOrderId);
722
+ await this.#transakDelete(`/api/v2/orders/${transakOrderId}`, {
723
+ cancelReason: 'Creating new order',
724
+ });
725
+ }
726
+ async cancelAllActiveOrders() {
727
+ this.#ensureAccessToken();
728
+ const activeOrders = await this.getActiveOrders();
729
+ const errors = [];
730
+ await Promise.all(activeOrders.map(async (order) => {
731
+ try {
732
+ const depositOrderId = TransakOrderIdTransformer.transakOrderIdToDepositOrderId(order.orderId, this.#environment);
733
+ await this.cancelOrder(depositOrderId);
734
+ }
735
+ catch (error) {
736
+ errors.push(error instanceof Error ? error : new Error(String(error)));
737
+ }
738
+ }));
739
+ return errors;
740
+ }
741
+ async getActiveOrders() {
742
+ this.#ensureAccessToken();
743
+ return this.#transakGet('/api/v2/active-orders');
744
+ }
745
+ }
746
+ //# sourceMappingURL=TransakService.js.map